• Stars
    star
    158
  • Rank 237,131 (Top 5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 12 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A simple, accessible show-and-hide/accordion script.

Houdini Build Status

A simple, accessible show-and-hide/accordion script.

Houdini progressively enhances your markup when it loads. You provide the content, and Houdini layers in the toggle buttons, ARIA attributes, and interactivity for you.

View the Demo on CodePen β†’

Getting Started | Accordions | Demos | API | What's New? | Browser Compatibility | License


Want to learn how to write your own vanilla JS plugins? Check out my Vanilla JS Pocket Guides or join the Vanilla JS Academy and level-up as a web developer. πŸš€


Getting Started

Compiled and production-ready code can be found in the dist directory. The src directory contains development code.

1. Include Houdini on your site.

Houdini has two required files: JavaScript and CSS.

There are two versions of the Houdini JavaScript file: the standalone version, and one that comes preloaded with polyfills for matches(), closest(), classList, and CustomEvent(), which are only supported in newer browsers.

If you're including your own polyfills or don't want to enable this feature for older browsers, use the standalone version. Otherwise, use the version with polyfills.

Direct Download

You can download the files directly from GitHub.

<link rel="stylesheet" type="text/css" href="/path/to/houdini.min.css">
<script src="path/to/houdini.polyfills.min.js"></script>

CDN

You can also use the jsDelivr CDN. I recommend linking to a specific version number or version range to prevent major updates from breaking your site. Houdini uses semantic versioning.

<!-- Always get the latest version -->
<!-- Not recommended for production sites! -->
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/cferdinandi/houdini/dist/css/houdini.min.js">
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/houdini/dist/js/houdini.polyfills.min.js"></script>

<!-- Get minor updates and patch fixes within a major version -->
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/cferdinandi/houdini@10/dist/css/houdini.min.js">
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/houdini@11/dist/js/houdini.polyfills.min.js"></script>

<!-- Get patch fixes within a minor version -->
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/cferdinandi/[email protected]/dist/css/houdini.min.js">
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/[email protected]/dist/js/houdini.polyfills.min.js"></script>

<!-- Get a specific version -->
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/cferdinandi/[email protected]/dist/css/houdini.min.js">
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/[email protected]/dist/js/houdini.polyfills.min.js"></script>

NPM

You can also use NPM (or your favorite package manager).

npm install houdinijs

2. Add the markup to your HTML.

  1. Wrap your content in a div element and assign it a unique ID.
  2. Add a selector (the example below uses the [data-houdini] attribute, but this could be a class or ID instead).
  3. Add a [data-houdini-button] attribute with the text you want for your button. Houdini will create the button and add any required ARIA attributes automatically when it loads.
<div data-houdini data-houdini-button="Show More" id="show-me">
	<p>Now you see me, now you don't.</p>
</div>

Note: The ID can serve as the selector. However, if you'll be including multiple disclosures with the same options and settings, it's better to use a shared selector like a class or data attribute for all of them.

3. Initialize Houdini.

In the footer of your page, after the content, initialize Houdini by passing in the selector for your disclosure component(s). And that's it, you're done. Nice work!

<script>
	var disclosure = new Houdini('[data-houdini]');
</script>

Here's a simple demo you can play with.

Accordions

Houdini also supports accordion groups.

Accordion Markup

For semantic reasons, these should have a heading/content relationship. You can use heading elements, data lists, and more.

The heading should have a [data-houdini-toggle] attribute, with a value equal to the ID of the content it toggles.

<h2 data-houdini-toggle="yo-ho-ho">Yo, ho ho!</h2>
<div data-houdini-group id="yo-ho-ho">Yo, ho ho and a bottle of rum!</div>

<h2 data-houdini-toggle="ahoy">Ahoy, there!</h2>
<div data-houdini-group id="ahoy">Ahoy there, matey!</div>

Accordion Initialization

Initialize an accordion by passing in the isAccordion option with a value of true.

var accordion = new Houdini('[data-houdini-group]', {
	isAccordion: true
});

If opening one accordion section should close any others in the group that are open, also include the collapseOthers option, with a value of true.

It's recommended that you give each group a unique selector if using this option.

var accordion = new Houdini('[data-houdini-group="pirates"]', {
	isAccordion: true,
	collapseOthers: true
});

Demos

API

Houdini includes smart defaults and works right out of the box. But if you want to customize things, it also has a robust API that provides multiple ways for you to adjust the default options and settings.

Expanded by Default

If you want specific disclosures or accordions to be expanded by default, add the .is-expanded class to your markup.

Expanded Disclosure

<div data-houdini class="is-expanded" id="show-me">
	<p>Now you see me, now you don't.</p>
</div>

Expanded Accordion

<h2 data-houdini-toggle="yo-ho-ho">Yo, ho ho!</h2>
<div data-houdini-group class="is-expanded" id="yo-ho-ho">Yo, ho ho and a bottle of rum!</div>

<h2 data-houdini-toggle="ahoy">Ahoy, there!</h2>
<div data-houdini-group id="ahoy">Ahoy there, matey!</div>

To expand all items by default, pass in the expanded option with a value of true.

// Disclosure expanded by default
var disclosure = new Houdini('[data-houdini]', {
	expanded: true
});

// Accordions expanded by default
var accordion = new Houdini('[data-houdini-group]', {
	isAccordion: true,
	expanded: true
});

Extra Info for Screen Readers

If you want to add extra information to your button for screen reader users, include the [data-houdini-label] attribute. This will add an aria-label to the button.

<div data-houdini data-houdini-button="Show More" data-houdini-label="Show more about pirates" id="show-me">
	<p>Now you see me, now you don't.</p>
</div>

Using Your Own Buttons

If you want to have more control over the toggle buttons, you can include your own instead.

Make sure your button has a [data-houdini-toggle] attribute with a value that matches the ID of the content it's supposed to toggle. You should also add the [hidden] attribute to hide the button until the script loads (Houdini will make it visible automatically).

<button data-houdini-toggle="show-me-too" aria-label="Show more about pirates, too" hidden>
	Show me, too
</button>

Note: You DO NOT need to include the [data-houdini-button] or [data-houdini-label] attributes, since you're creating your own button and can add that content directly.

Options and Settings

You can override the default settings by passing in user options as a second argument when instantiating.

var disclosure = new Houdini('[data-houdini]', {

	// Content
	contentClass: 'houdini',
	expanded: false,
	expandedClass: 'is-expanded',

	// Toggle Buttons
	btnAfter: false, // If true, load toggle button after the content
	btnClass: 'houdini-toggle', // The class to add to toggle buttons
	btnAttribute: 'data-houdini-toggle', // The data attribute to use for toggle buttons
	btnTextAttribute: 'data-houdini-button', // The data attribute for the button text
	btnLabelAttribute: 'data-houdini-label', // The data attribute for aria-label text
	btnPreexisting: 'data-houdini-button-preexisting', // The data attribute added to pre-existing buttons

	// Accordion
	isAccordion: false, // If true, treat as an accordion
	collapseOthers: false, // If true, only allow on open piece of content at a time
	headingClass: 'houdini-heading', // The class to add to the heading element

	// Icons
	icon: -1, // If true, include an expand/collapse icon
	iconClass: 'houdini-toggle-icon', // The class to use for the expand/collapse icon
	iconAttribute: 'data-houdini-icon', // The data attribute to use for the expand/collapse icon
	iconShow: '+', // The icon to expand an accordion
	iconHide: '&ndash;', // The icon to collapse an accordion

	// Custom Events
	emitEvents: true // If true, emit custom events

});

Custom Events

Houdini emits five custom events:

  • houdiniExpand is emitted on a content element after it's expanded.
  • houdiniCollapse is emitted on a content element after it's collapsed.
  • houdiniInitialize is emitted on the document when the script is initialized, but before the DOM is setup.
  • houdiniSetup is emitted on the document after the DOM is setup.
  • houdiniDestroy is emitted on the document after an initialization is destroyed.

On the houdiniExpand and houdiniCollapse event, the event.detail object includes the content and button. For the houdiniInitialize, houdiniSetup, and houdiniDestroy event, it includes the settings object.

All five events bubble, and can be captured with event delegation.

// Log scroll events
var logHoudiniEvent = function (event) {

	// The event type
	console.log('type:', event.type);

	// The content being expanded or collapsed
	console.log('content:', event.detail.content);

	// The button for the content
	console.log('button:', event.detail.button);

};

// Listen for scroll events
document.addEventListener('houdiniExpand', logHoudiniEvent, false);
document.addEventListener('houdiniCollapse', logHoudiniEvent, false);

Methods

You can also call Houdini's methods in your own scripts.

toggle()

Toggle the visibility of a content area. Accepts an element or selector string as an argument. Can be the toggle or content.

var disclosure = new Houdini();

// Selector string
disclosure.toggle('#yo-ho-ho');

// Content element
var content = document.querySelector('#yo-ho-ho');
disclosure.toggle(content);

// Button element
var btn = document.querySelector('[data-houdini-toggle="yo-ho-ho"]');
disclosure.toggle(btn);

expand()

Expand a content area. Accepts an element or selector string as an argument. Can be the toggle or content.

var disclosure = new Houdini();

// Selector string
disclosure.expand('#yo-ho-ho');

// Content element
var content = document.querySelector('#yo-ho-ho');
disclosure.expand(content);

// Button element
var btn = document.querySelector('[data-houdini-toggle="yo-ho-ho"]');
disclosure.expand(btn);

collapse()

Collapse a content area. Accepts an element or selector string as an argument. Can be the toggle or content.

var disclosure = new Houdini();

// Selector string
disclosure.collapse('#yo-ho-ho');

// Content element
var content = document.querySelector('#yo-ho-ho');
disclosure.collapse(content);

// Button element
var btn = document.querySelector('[data-houdini-toggle="yo-ho-ho"]');
disclosure.collapse(btn);

setup()

Adds the required markup to the DOM. This runs automatically when you initialize Houdini, but if you add new elements to the DOM later, you should run it again.

var disclosure = new Houdini('[data-houdini]');

// Some time later...
disclosure.setup();

destroy()

Destroy an instantiation of Houdini and restore the markup to its original state.

var disclosure = new Houdini('[data-houdini]');

// Some time later...
disclosure.destroy();

What's New?

  • Supports multiple instantiations at once.
  • Better accessibility and semantics.
  • Automatically progressively enhances your markup for you.
  • Deprecated callbacks in favor of custom events.

Migrating to Houdini 11 from Houdini 10

Based on feedback from accessibility experts, Houdini no longer supports changing button text or using the same text for all buttons.

  • Every content area now needs a [data-houdini-button] attribute or a button element with a [data-houdini-toggle] attribute that matches the content ID.
  • The btnShow and btnHide options no longer exist.

Migrating to Houdini 10 from Older Versions

The entire markup and initialization process has changed in Houdini 10. To migrate:

  • Remove existing toggle buttons from your markup.
  • Switch the .active to .is-expanded for content you want expanded by default.
  • Accordions should use a semantic heading/content relational structure instead of anchor links.
  • Instantiate Houdini with new Houdini() instead of houdini.init().
  • Move any callbacks to custom event listeners.

Kudos πŸ‘

Major kudos to Scott O'Hara for walking me through the nuances of accordion accessibility and giving me tons of feedback along the way.

Browser Compatibility

Houdini works in all modern browsers, and IE 9 and above.

Houdini is built with modern JavaScript APIs, and uses progressive enhancement. If the JavaScript file fails to load, or if your site is viewed on older and less capable browsers, all of your content will be displayed as-is.

Polyfills

Support back to IE9 requires polyfills for matches(), closest(), classList, and CustomEvent(). Without them, support starts with Edge.

Use the included polyfills version of Houdini, or include your own.

License

The code is available under the MIT License.

More Repositories

1

smooth-scroll

A lightweight script to animate scrolling to anchor links.
JavaScript
5,481
star
2

reef

A lightweight library for creating reactive, state-based components and UI.
JavaScript
1,113
star
3

gulp-boilerplate

A boilerplate for building web projects with Gulp.js.
JavaScript
846
star
4

kraken

A lightweight, mobile-first boilerplate for front-end web developers.
HTML
768
star
5

gumshoe

A simple vanilla JS scrollspy script.
JavaScript
731
star
6

social-sharing

Add social sharing links and buttons without the bloat.
CSS
641
star
7

tabby

Lightweight, accessible vanilla JS toggle tabs.
JavaScript
577
star
8

atomic

A tiny, Promise-based vanilla JS Ajax/HTTP plugin with great browser support.
HTML
540
star
9

build-tool-boilerplate

A simple boilerplate for using NPM tasks to build and compile JavaScript, CSS, and image files.
JavaScript
488
star
10

bouncer

A lightweight form validation script that augments native HTML5 form validation elements and attributes.
JavaScript
308
star
11

validate

A lightweight form validation script.
JavaScript
230
star
12

ebook-boilerplate

A lightweight boilerplate for self-publishing ebooks with markdown and command line.
CSS
135
star
13

htaccess

[DEPRECATED] Best practice server rules for making web pages fast and secure.
ApacheConf
93
star
14

slider

[DEPRECATED] A simple, fluid, touch-enabled carousel.
JavaScript
87
star
15

right-height

Dynamically set content areas of different lengths to the same height.
CSS
87
star
16

modals

Simple modal dialogue windows
JavaScript
85
star
17

bin

A tiny (<1kb) localStorage and sessionStorage helper library.
JavaScript
84
star
18

vanilla-javascript-cheat-sheet

Moved
80
star
19

vanilla-js-toolkit

A growing collection of vanilla JavaScript code snippets, helper functions, polyfills, plugins, and learning resources.
CSS
79
star
20

drop

A small CSS component that turns browser-native <details> elements into dropdown menus.
JavaScript
75
star
21

form-saver

A simple script that lets users save and reuse form data.
JavaScript
68
star
22

hugo-starter

A barebones starter project and theme for learning Hugo.
HTML
67
star
23

gmt-wordpress-for-web-apps

[DEPRECATED] A plugin that provides the essential components you need to power your web app with WordPress.
PHP
67
star
24

events

A tiny event delegation library.
JavaScript
62
star
25

gmt-html-minify

Minify your HTML output in WordPress.
PHP
61
star
26

buoy

[DEPRECATED] A lightweight collection of helper methods for getting stuff done with native JavaScript.
JavaScript
54
star
27

astro

Mobile-first navigation patterns.
JavaScript
53
star
28

sticky-footer

Dynamic, responsive sticky footers.
JavaScript
47
star
29

keel

A lightweight boilerplate for WordPress theme developers.
JavaScript
46
star
30

x-ray

X-Ray is a script that lets users toggle password visibility in forms.
JavaScript
46
star
31

table-of-contents

Automatically generate a table of contents from the headings on the page.
JavaScript
39
star
32

jar

A tiny (< 1kb) library that makes working with cookies easier.
JavaScript
38
star
33

saferInnerHTML

Set the HTML of an element while protecting yourself from XSS attacks.
JavaScript
29
star
34

dom-manipulation-source-code

HTML
24
star
35

gmt-image-compress-and-sharpen

[DEPRECATED] Change the default WordPress compression rate for JPGs, convert images to progressive JPGs, and sharpen images.
PHP
19
star
36

learn-vanilla-js

A roadmap for learning vanilla JavaScript
HTML
19
star
37

jellyfish

[DEPRECATED] A progressively enhanced image lazy loader.
JavaScript
18
star
38

frontend-horse-js-library

The boilerplate for the Frontend Horse livestream.
JavaScript
17
star
39

state-based-ui-source-code

JavaScript
15
star
40

petfinderAPI4everybody

A JavaScript plugin that makes it easier to use the Petfinder API.
JavaScript
14
star
41

vanilla-js-guides

HTML
14
star
42

wp-shopping-cart

[DEPRECATED - DO NOT USE] A simple PayPal shopping cart for WordPress.
PHP
14
star
43

alerts

Simple alert messages.
JavaScript
14
star
44

wp-theme-options

[DEPRECATED] Create a theme options menu that admin can use to adjust theme settings from the dashboard.
PHP
14
star
45

reef-js

The website for ReefJS.
HTML
14
star
46

progress-bars

Simple CSS progress bars.
CSS
13
star
47

writing-libraries-source-code

HTML
13
star
48

learn-vanilla-js-source-code

HTML
12
star
49

kelp

A collection of small functions for creating reactive, state-based UIs.
JavaScript
12
star
50

project-star-rating-system

A vanilla JavaScript project
HTML
11
star
51

gmt-mailchimp-wp-rest-api

Add WP Rest API hooks for JS use of the Mailchimp API.
PHP
11
star
52

apis-source-code

HTML
11
star
53

vanilla-js-list

A growing list of organizations that build sites and apps with vanilla JS
CSS
10
star
54

petfinder-api-for-wordpress

A collection of functions to help you display Petfinder listings on your WordPress site.
PHP
10
star
55

browser-storage-source-code

HTML
10
star
56

gmt-pricing-parity

Display country-specific EDD discounts to visitors.
PHP
9
star
57

vanilla-js-academy

PHP
9
star
58

gmt-remove-header-junk

[DEPRECATED] Remove the unneccessary junk WordPress adds to the header.
PHP
9
star
59

snapshot

Simple image styling.
CSS
9
star
60

dom-injection-source-code

HTML
8
star
61

the-lean-web

CSS
8
star
62

sw-fonts

Demo for https://gomakethings.com/improving-web-font-performance-with-service-workers/
HTML
8
star
63

gmt-paypal-ipn-forwarder

[DEPRECATED] Forward PayPal IPN to multiple other IPN services in WordPress.
PHP
8
star
64

service-worker-pages-demo

A demo for https://gomakethings.com/saving-recently-viewed-pages-with-service-workers-and-vanilla-js/
HTML
8
star
65

gmt-slack-invites-for-edd

[DEPRECATED] Automatically invite members to your Slack team when they purchase a product.
PHP
8
star
66

vanilla-js-guidebook-labs

The labs for "The Vanilla JS Guidebook."
HTML
7
star
67

service-workers-source-code

JavaScript
7
star
68

sw-offline-first

Demo for https://gomakethings.com/offline-first-with-service-workers-and-vanilla-js/
HTML
7
star
69

harbor-wp-theme

A free mobile-friendly WordPress theme built specifically for animal rescue organizations.
JavaScript
7
star
70

adventure

A simplish, imagination-based kitchen table RPG.
CSS
7
star
71

vanilla-js-projects

HTML
6
star
72

games

Simple vanilla JS game demos.
HTML
6
star
73

variable-function-scope-source-code

HTML
6
star
74

gmt-automated-slack-invites

Automate Slack invites with WordPress.
PHP
6
star
75

google-hosted-jquery

[DEPRECATED] Use the Google CDN version of jQuery in WordPress, with a local fallback.
PHP
6
star
76

gomakethings

The WordPress theme for Go Make Things
JavaScript
5
star
77

service-worker-demo

A demo for https://gomakethings.com/writing-your-first-service-worker-with-vanilla-js/
HTML
5
star
78

origami

[DEPRECATED] Origami has been merged into the Kraken front-end boilerplate and is no longer supported.
HTML
5
star
79

timezones

Easily calculate timezones for your next meeting.
HTML
4
star
80

arrays-objects-source-code

HTML
4
star
81

labels

Lightweight CSS labels.
CSS
4
star
82

gmt-antispambot

A shortcode for the antispambot function that's built into WordPress.
PHP
4
star
83

cferdinandi

4
star
84

web-components-source-code

HTML
4
star
85

string-array-object-source-code

HTML
4
star
86

vanilla-js-podcast

A show about JavaScript for people who hate the complexity of modern front‑end web development.
CSS
4
star
87

es-modules-demo

https://gomakethings.com/an-intro-to-import-and-export-with-es-modules/
JavaScript
3
star
88

javascript-essentials-source-code

Source code for the JavaScript Essentials workshop.
HTML
3
star
89

accessible-components-source-code

HTML
3
star
90

es-modules-source-code

JavaScript
3
star
91

ajax-source-code

HTML
3
star
92

strings-numbers-source-code

HTML
3
star
93

go-mobile-first

[DEPRECATED] A mobile-first boilerplate for WordPress.
PHP
3
star
94

gmt-allow-iframes

[DEPRECATED] Prevent wp_kses from removing iframe embeds
PHP
3
star
95

gmt-donations

[DEPRECATED] A WordPress plugin that lets you create powerful donation forms that integrate with Stripe and PayPal Express Checkout.
PHP
3
star
96

token-based-authentication-source-code

HTML
3
star
97

advanced-academy-common-issue-not-modularizing-your-code-enough

JavaScript
3
star
98

fetch

The Fetch for Petfinder plugin
JavaScript
2
star
99

es-modules-default

https://gomakethings.com/how-to-define-a-default-export-with-vanilla-js-es-modules/
JavaScript
2
star
100

careers

CSS
2
star