monkthemighty
monkthemighty

Reputation: 135

How to hide a list without javascript

I have this code and I would like to have the list be collapsed by default. Here is what it does now.

<!DOCTYPE html>
<head>
   <title>menu mockup</title>
   <style type="text/css">
      .show {display: none; }
      .hide:focus + .show {display: inline; }
      .hide:focus { display: none; }
      .hide:focus ~ #list { display:none; }
      @media print { .hide, .show { display: none; } }
   </style>
</head>
<body>
   <p>Here's a list</p>
      <div>
         <a href="#" class="hide">[hide]</a>
         <a href="#" class="show">[show]</a>
         <ol id="list">
            <li>item 1</li>
            <li>item 2</li>
            <li>item 3</li>
         </ol>
      </div>
   <p>How about that?</p>
</body>
</html>

Upvotes: 2

Views: 6791

Answers (2)

klark
klark

Reputation: 494

This html code collapses the list by default

<!DOCTYPE html>
<head>
   <title>menu mockup</title>
   <style type="text/css">
      .show {display: inline; text-decoration: none;}
      .hide {display: none; text-decoration: none;}
      #list {display: none;}
      .show:focus + .hide {display: inline;}
      .hide:focus + #list { display:none;}
      .show:focus ~ #list { display:inline;}
      .show:focus { display:none;}

   </style>
</head>
<body>
   <p>Here's a list</p>
      <div>


         <a href="#" class="show">&#x25BC</a>
         <a href="#" class="hide">&#x25B2</a>
         <ol id="list">
            <li>item 1</li>
            <li>item 2</li>
            <li>item 3</li>
         </ol>

      </div>
  </body>
</html>

Upvotes: -1

David Thomas
David Thomas

Reputation: 253318

For this to work in pure CSS requires a change to the HTML (since CSS can only target elements that appear later in the DOM (either as later-siblings, or descendants, or a combination of those two) than the elements upon which they're styled. So, the HTML is now:

<p>Here's a list</p>
<div id="top">
    <ol id="list">
        <li>item 1</li>
        <li>item 2</li>
        <li>item 3</li>
    </ol>
    <a href="#top" class="hide">[hide]</a>
    <a href="#list" class="show">[show]</a>
</div>
<p>How about that?</p>​

Note also that the div now has an id in order to allow for the list to be hidden (again, using just CSS and basic HTML).

The CSS is somewhat convoluted, though explained through /* comments in the CSS itself */:

.show,
.hide {
    /* allows for the links to be positioned 'ahead' of the list
       whose appearance they control */
    position: absolute;
    top: 0.1em;
    /* allows for an assigned width, height, etc... */
    display: inline-block;
    width: 5em;
    height: 2em;
    line-height: 2em;
    text-align: center;
}

.hide {
    left: 0;
}

.show {
    /* this is why we have an assigned width */
    left: 5.1em;
}

#list {
    /* hides on page-load */
    display: none;
}

#list:target {
    /* when clicking the 'show' link the #list is targeted
       and is shown */
    display: block;
}

#list:target ~ .show {
    /* reduces the opacity of the 'show' link, when
       the list is already shown */
    opacity: 0.3;
}

#list:target ~ .hide {
    /* when the list is shown, the 'hide' link is visible */
    opacity: 1;
}

#top {
    /* allows the links to be positioned visually ahead of,
       and relative to, the menu */
    position: relative;
    /* slightly greater than the defined height of
       the link elements */
    padding-top: 2.2em;
}

#top .hide,
#top:target  .hide {
    /* hides the 'hide' link when the list is, itself, hidden */
    opacity: 0.3;
}

JS Fiddle demo.

A slightly revised (another element added to wrap the links) version, to allow for more easily positioning them (rather than having to manually work out how wide each link is before setting the left position):

<p>Here's a list</p>
<div id="top">
    <ol id="list">
        <li>item 1</li>
        <li>item 2</li>
        <li>item 3</li>
    </ol>
    <!-- could use a div, it doesn't matter -->
    <span id="controls">
        <a href="#top" class="hide">[hide]</a>
        <a href="#list" class="show">[show]</a>
    </span>
</div>
<p>How about that?</p>​

With the CSS:

#controls {
    position: absolute;
    top: 0.1em;
    left: 0;
    height: 2em;
    line-height: 2em;
}

.show,
.hide {
    display: inline-block;
    width: 5em;
    text-align: center;
}

#list {
    display: none;
}

#top {
    position: relative;
    padding-top: 2.2em;
}

#list:target {
    display: block;
}

#list:target ~ #controls .hide {
    opacity: 1;
}

#list:target ~ #controls .show {
    opacity: 0.3;
}

#top #controls .hide {
    opacity: 0.3;
}
#top:target #controls .hide {
    opacity: 0.3;
}

JS Fiddle demo.

Or, instead, using visibility: hidden / visibility: visible;.

Upvotes: 2

Related Questions