Skip to content

Instantly share code, notes, and snippets.

@hsquareweb
Last active December 14, 2016 15:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hsquareweb/61e0f8961e34c7b85b88c544fcfe932c to your computer and use it in GitHub Desktop.
Save hsquareweb/61e0f8961e34c7b85b88c544fcfe932c to your computer and use it in GitHub Desktop.
Tabs
How tabs should work by
https://remysharp.com/2016/12/11/how-tabs-should-work
- Navigable available without JavaScript
- Anchor links that are, clickable, have block layout, have their href pointing to the id of the panel element, uses correct cursor (ie. cursor: pointer).
- Since tabs are clickable, the user can open in a new tab/window and the page correctly loads with the right tab open.
- Right clicking (and shift-clicking) doesn't cause the tab to be selected.
- Browser native back/forward button correctly changes the state of the selected tab (think - about it working exactly as if there was no JavaScript in place).
Final version: http://output.jsbin.com/lorovu/
ul.tabs {
margin: 0;
padding: 0;
list-style: none;
overflow: hidden;
margin-bottom: 10px;
}
ul.tabs a {
border: 1px solid #ccc;
padding: 10px;
margin-right: 10px;
float: left;
display: block;
color: #000;
text-decoration: none;
}
ul.tabs a:hover {
background: #000;
border-color: #000;
color: #fff;
}
ul.tabs a.selected,
ul.tabs a[aria-selected='true'] {
background: #ccc;
border-color: #ccc;
color: #000;
}
.panel {
padding: 10px;
width: 550px;
overflow: hidden;
border: 1px solid #ccc;
overflow: scroll;
margin-bottom: 10px;
}
div[aria-hidden='true'] {
display: none;
}
<ul class="tabs">
<li><a class="tab" href="#dizzy">Dizzy</a></li>
<li><a class="tab" href="#ninja">Ninja</a></li>
<li><a class="tab" href="#missy">Missy</a></li>
</ul>
<div id="dizzy">
<!-- panel content -->
</div>
<div id="ninja">
<!-- panel content -->
</div>
<div id="missy">
<!-- panel content -->
</div>
/*global $*/
// a temp value to cache *what* we're about to show
var target = null;
// collect all the tabs
var tabs = $('.tab').on('click', function () {
console.log('click')
target = $(this.hash).removeAttr('id');
if (location.hash === this.hash) {
setTimeout(update);
}
}).attr('tabindex', '0');
// get an array of the panel ids (from the anchor hash)
var targets = tabs.map(function () {
return this.hash;
}).get();
// use those ids to get a jQuery collection of panels
var panels = $(targets.join(',')).each(function () {
// keep a copy of what the original el.id was
$(this).data('old-id', this.id);
});
function update() {
console.log('update')
if (target) {
target.attr('id', target.data('old-id'));
target = null;
}
var hash = window.location.hash;
if (targets.indexOf(hash) !== -1) {
return show(hash);
}
// NOTE: this was added after the article was written
// to fix going "back" on the browser nav to an empty state
if (!hash) {
show();
}
}
function show(id) {
// if no value was given, let's take the first panel
if (!id) {
id = targets[0];
}
// remove the selected class from the tabs,
// and add it back to the one the user selected
tabs.removeClass('selected').attr('aria-selected', 'false').filter(function () {
return (this.hash === id);
}).addClass('selected').attr('aria-selected', 'true');
// now hide all the panels, then filter to
// the one we're interested in, and show it
panels.hide().attr('aria-hidden', 'true').filter(id).show().attr('aria-hidden', 'false');
}
window.addEventListener('hashchange', update);
// initialise
if (targets.indexOf(window.location.hash) !== -1) {
update();
} else {
show();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment