Last Updated: May 31, 2021
·
19.57K
· uniqname

All CSS hover activated accordion with default state

The kicker is the default state. You want a specified section of the accordion to be open if the accordion itself isn't being interacted with.

The trick is nested hover states.

The Markup

<div class="accordion">
    <section>
        <h1>Section 1</h1>
        <div class="accordion_content">
            <p>Content for section 1</p>
        </div>
    </section>
    <section>
        <h1>Section 2</h1>
        <div class="accordion_content">
            <p>Content for section 2</p>
        </div>
    </section>
    <section class="default">
        <h1>Section 3</h1>
        <div class="accordion_content">
            <p>Content for section 3</p>
            <p>This is my default state.</p>
        </div>
    </section>
    <section>
        <h1>Section 4</h1>
        <div class="accordion_content">
            <p>Content for section 4</p>
        </div>
    </section>
</div>

The CSS

Code for the static state (e.g. when nothing is being hovered on) and with no default.

.accordion section > .accordion_content {
    height: 0;
    overflow: hidden;
    transition: height .25s;
}

Next add the hover state style.

.accordion section:hover > .accordion_content {
    height: 6em;
}

We now have a working accordion. That's not all that impressive though. We want one with a specified panel open as default. One that will always be open if the user isn't hovering over a different panel.

Note that the style for the hover state is the same as the default state. So let's add that selector to the rule.

.accordion section:hover > .accordion_content,
.accordion section.default > .accordion_content {
    height: 6em;
}

Ok, now we have a default state, but that one never closes when we are interacting with the other panels. We need a rule that will collapse the default state if we hover over a different panel. We could try using the general sibling selector (~), but we will run into trouble if we want a default open state for any panel other than the last one.

We could try some big complicated set of selectors and rules, but I'm not sure it would actually work, and in any case lets keep the code terse.

The magic

The trick is to use the cascading nature of CSS as well as nested :hover states.

First we want to close ALL panels when hovering over the accordion container.

.accordion:hover > .accordion_content {
    height: 0;
}

Next we want to open the specific panel we are hovering over, remembering that we are already hovering over the accordion container.

.accordion:hover > .accordion_content:hover {
    height: 6em;
}

Well that works, but we have more lines of code here than we need. Let's clean up.

We can combine the accordion container hover selector with our earlier style for the panels that aren't our default

.accordion section > .accordion_content,
.accordion:hover > .accordion_content {
    height: 0;
    overflow: hidden;
    transition: height .25s;
}

We can also replace the earlier hover functionality rule with the nested hover selector. The are functionally equivalent.

.accordion:hover section:hover > .accordion_content,
.accordion section.default > .accordion_content {
    height: 6em;
}

Bam! There we have it. A terse, All CSS, hover activated accordion with a default state.

.accordion:hover section:hover > .accordion_content,
.accordion section.default > .accordion_content {
    height: 6em;
}

.accordion section > .accordion_content,
.accordion:hover section > .accordion_content {
    height: 0;
    overflow: hidden;
    transition: height .25s;
}

Everything after that is aesthetics.

Checkout the Codepen demo

2 Responses
Add your response

You can remove the :hover from accordion:hover in the first line.

http://codepen.io/anon/pen/bGACo

over 1 year ago ·

Hello, and thank you, this is the best accordion I have seen.
I have a problem, because I can not control the output of a CMS, I get 3 summaries for the accordion: class="accordion-item" and I cannot inject the "accordion-item--default" Is there a solution to this?, because I can have access to the css file but not to the generated html, I can modify only a template for the html generation where there is a single general templated division for each of the 3 summaries, the templated division can accept classes that will be applied for all divisions in the output with no possibility to modify a class for the first division, that is what I want open by default.
Due to this limitation I have a working accordion but all divisions are closed by default.
Thanks in advance for your help.
Regards
Jose

over 1 year ago ·