添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

The “Checkbox Hack” is where you use a connected <label> and <input type="checkbox"> and usually some other element you are trying to control, like this:

<label for="toggle">Do Something</label>
<input type="checkbox" id="toggle">
<div class="control-me">Control me</div>

Then with CSS, you hide the checkbox entirely. Probably by kicking it off the page with absolute positioning or setting its opacity to zero. But just because the checkbox is hidden, clicking the <label> still toggles its value on and off. Then you can use the adjacent sibling combinator to style the <div> differently based on the :checked state of the input.

.control-me {
  /* Default state */
#toggle:checked ~ .control-me {
  /* A toggled state! No JavaScript! */

So you can style an element completely differently depending on the state of that checkbox, which you don’t even see. Pretty neat. Let’s look at a bunch of things the “Checkbox Hack” can do.

See the Pen
The Checkbox Hack
by Chris Coyier (@chriscoyier)
on CodePen.

Some of this stuff crosses the line of what you “should” do with CSS and introduces some questionable semantics. It’s still very fun to play with and cool that it’s possible, but in general, functional behavior should be controlled by JavaScript.

Custom Designed Radio Buttons and Checkboxes

See the Pen
Custom checkboxes with CSS only
by Geoffrey Crofte (@GeoffreyCrofte)
on CodePen.

You can hide the default UI of a radio button or checkbox, and display a custom version right on top of it.

  • Pioneered by Ryan Seddon
  • Similar by Martin Ivanov
  • For use on Wufoo forms by me
  • File system like “tree menu”

    Demo by Ryan Seddon

    Tabbed Areas

    The “tabs” design pattern is just toggling on and off of areas, perfect for the checkbox hack. But instead of checkboxes, in which any checkbox can be on or off independently of one another, these tabs use radio buttons in which only one per group can be on at a time (like how only one tab can be active at a time).

    Demo from Functional CSS tabs revisited:

    See the Pen
    Functional CSS Tabs
    by Chris Coyier (@chriscoyier)
    on CodePen.

    Dropdown Menus

    See the Pen
    Radio Button Dropdowns
    by Chris Coyier (@chriscoyier)
    on CodePen.

    Push Toggles

    A toggle can take the form of ON/OFF, which can be done with a single <input type="checkbox">. Like emoji toggles!

    See the Pen
    CSS Checkbox Toggle Switch
    by Chris Coyier (@chriscoyier)
    on CodePen.

    Or it could be multiple <input type="checkbox"> elements to switch between differnet distinct values.

    FAQ Answer Revealing

    You’d probably just use a <details>/<summary> combo for this these days, but expandable sections can be done with the checkbox hack.

    See the Pen
    FAQ without Details/Summary (checkbox hack)
    by Chris Coyier (@chriscoyier)
    on CodePen.

    Hide the Sidebar

    Like the old school Octopress theme.

    See the Pen
    Hide the Sidebar with Checkbox Hack
    by Chris Coyier (@chriscoyier)
    on CodePen.

    @Mathias: My initial thought was the same. But then on second though; I don’t think so. How would that work? For browsers that support details/summary, no such thing is needed. For all other browsers, we would need a polyfill script anyway. I’m assuming you’re not suggesting that we manually include a checkbox alongside every details/summary instance, as that would be the worst of both worlds.

    That’s a very bad idea: to use styles like “left: -9999px”. Once you turn direction to rtl there will be large horizontal scroll. Perhaps, it would be there already if someone with system RTL settings such as hebrew, arabian or hindi visits your site—I haven’t tested this.
    It’s a much better idea to use styles like “clip:rect(0 0 0 0);” (seen in Lea Verou presentation). “” is also ok if IE browsers aren’t concerned.

    There’s a lot to learn from the CSS part but the HTML part is nonsense: form elements are to be used in forms (*), not in navigation lists, tabs or treelists.

    Simple questions: where’s the form element? Where’s the submit button?
    Advice: if it’s not a form, don’t use form elements.

    The other “problem” is that CSS Tricks is a successful website with many visitors: Chris Coyer deserves this success but on the other part comes “some” responsibility for beginners and not so beginners that are not sure about their skills and knowledge of good practice.
    In my opinion, this is “Stuff you must not do but still can learn from”. Chris added a disclaimer (even huge disclaimers wouldn’t stop few people to copypaste everything they see but it’s their problem) but I still read the title as “This is stuff I can do? OK I’ll do that”. And people like me will complain that “some of this stuff crosses the line” and “some bad semantics” is too vague (I didn’t see good semantics here though, again, there’s a lot to learn from the CSS part).
    If you need tabs or a treelist on your site, use JS to hide and show content and check http://hanshillen.github.com/jqtest/

    (*) I know that due to limitations in the HTML4.01 recommendation (there isn’t a way to express the fact that an input can be nested in a %block% like p or a fieldset or a fieldstet into a fieldset, etc), many things like a fieldset outside a form are valid but it still doesn’t make sense in a website.

    I generally agree that inputs shouldn’t be used outside forms, but there’s nothing wrong with using a <button type="button"> outside a form, so there are certainly situations for everything. It’s a focusable element and, in maybe cases, a more accessible solution for hiding/showing content than current popular methods.

    Your comment was a little harsh and I think you’re taking this proof of concept stuff too seriously.

    The Internet is mostly a bunch of links, forms and text. It’s nice to see something a little different from time to time.

    @Felipe Chris did put a disclaimer there, and people who want to learn can do whatever you want. Nowadays forms are used so much that they could hardly be called that anymore. This is even more of a blogpost than a tutorial anyway.
    People can do what they want with what they’ve learned; if you’re working on your own, you technically only have to be as semantic as you need.

    For me, the disclaimer is right in the title. “Hack”. Chris makes it plainly clear that this is something that will gain you an even deeper understanding of the canvas you’re painting on and, due to its non-semantics should really only be implemented in the funnest of cases (or those that relate to us as web manipulators, like Dabblet).

    Nice writeup Chris!

    You should add user-select: none; for label to prevent selecting text in buttons and to improve usability.

    -webkit-user-select: none;
    	-khtml-user-select: none;
    	-moz-user-select: none;
    	-o-user-select: none;
    	user-select: none;

    Was Just about to say the same thing (yes, I’m a different person than Arto, just a coincidentally similar name). If I remember right, though, you still end up with a situation where clicking on the label quickly will not register every click as toggling the associated checkbox.

    In light of this, I typically have to use JavaScript and a non-label trigger with two-way state change (clicking the non-label trigger updates the checkbox state, changing the checkbox state updates the trigger’s appearance). Combined with leaving the checkbox positioned off the page but not visible, this still leaves the checkbox accessible via keyboard shortcuts (which is always a concern when replacing an existing element).

    I’d love to see a version of this hack work with rapid-succession clicks on the label, though. The JavaScript for the above isn’t exactly simple.

    Verified the above. Even with the user-select on the label and the input, clicking rapidly on the label does not register every click.

    http://dabblet.com/gist/1510457

    Cant seem to get the tabs to work if they are nested. Does anyone have any ideas how to fix this problem?

    http://dl.dropbox.com/u/14080718/CSSTabs/index.html

    I made a lion css ui kit recently and used the checked state for the source list so radio buttons track the selected item and checkboxes handle the treeview.

    Writing the html for a tree menu by hand gets laborous pretty quickly. For segmented push toggles the technique does feel kinda right though.

    While I agree most of these examples probably shouldn’t be used in practice, I think the “Push Toggle” examples are actually a perfect use case for this technique. Semantically, those are radio buttons, so it makes sense to have actual radio buttons in your markup. You could fall back to plain old radio buttons w/ labels in unsupported browsers.

    I’ve accomplished the same effect using extra markup for the styled toggles and javascript to manage the state of the hidden radio buttons, but this approach is much cleaner.

    To make it work in IE7/8 you can add a little jquery script:

    if ($.browser.msie && parseInt($.browser.version) < 9) { $('input[type="checkbox"]').change(function() { $(this).toggleClass('checked', this.checked).parent().hide().show(); }).each(function() { $(this).toggleClass('checked', this.checked).parent().hide().show();

    and just copy style and relpace :checked with .checked:

    input[type="checkbox"]:checked + label { ... } input[type="checkbox"].checked + label { ... }

    Would be great if as part of the title area for all articles there was a little sub-header similar to the author one, or an icon or similar to classify what versions of html and css are being targeted in the article (eg. HTML5 & CSS3 or HTML4 & CSS3 etc).

    Unfortunately for some of us (maybe just me) its not immediately obvious what version is being targeted.

    Really great and helpful article. Hacks always for shortcut but that always work and became long time solution. I found nice article about CSS hacks.
    http://wordpressapi.com/2011/01/24/50-css-tequniqe-tips-web-developer-check/

    I have a problem to this in IE 8….
    Does someone know how to make it work in this Evil browser??

    I have This code:
    input[type=checkbox]{
    position: absolute;
    left: -9999px;
    overflow: hidden;

    input[type=checkbox].checked ~ div {
    background-position: 5% -19px;
    background-color: #E5F6FF;
    border: 1px solid #D1EFFF;

    The IE 8 ignores it while all other borwser (chrome,FF,Safari and Opera) handle it easily.

    what should i do?

    Is there any way to prevent the page from jumping when a user selects the label? If there is any amount of scrolling required to get to the label, clicking it will make the page jump to the top.

    Any ideas as to how to get around this?

    It’s also helpful to note that putting the label before the checkbox doesn’t allow it to be styled, since CSS cannot traverse up the DOM (only down) AFAIK. Something like this:

    HTML:
        <label for="toggle">Toggle</label>
        <input type="checkbox" id="toggle">
        input[type="checkbox"]:checked ~ label {
            background: red;
    

    Will not work, but the exact same code with the two HTML lines reversed will work fine. This is because the label element doesn’t exist for the CSS :checked selector.

    Since the ~ selector only has access to immediate siblings, nesting the checkbox inside a label also will not work, unless the target is inside the label as well.

    Very useful post, I’m using it for a responsive fly-down navigation pane for mobile devices which seems to be working great!