Pure CSS clickable dropdown?
Asked Answered
R

4

10

This tutorial explains how to use the :hover pseudo-class to style HTML elements on hover and how to how create a dropdown when hovering over a particular element in pure CSS (without using any JavaScript).

Is it possible to create the same dropdown as the one in the example below, in pure CSS, but when clicking an element instead of when hovering over it?

I would prefer to use no JavaScript at all, or - if not possible without JavaScript - as little JavaScript as possible. The items of the drowndown should be clickable themselves.

Example:

.dropdown {
    position: relative;
    display: inline-block;
}

.dropbtn {
    background-color: #4CAF50;
    color: white;
    padding: 16px;
    font-size: 16px;
    border: none;
    cursor: pointer;
}

.dropdown-content {
    display: none;
    position: absolute;
    right: 0;
    background-color: #f9f9f9;
    min-width: 160px;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    z-index: 1;
}

.dropdown-content a {
    color: black;
    padding: 12px 16px;
    text-decoration: none;
    display: block;
}

.dropdown-content a:hover {background-color: #f1f1f1}

.dropdown:hover .dropdown-content {
    display: block;
}

.dropdown:hover .dropbtn {
    background-color: #3e8e41;
}
<div class="dropdown" style="float:left;">
  <button class="dropbtn">Left</button>
  <div class="dropdown-content" style="left:0;">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>
</div>
Rhomb answered 29/6, 2017 at 18:32 Comment(8)
Could possibly do with clever use of the focus eventSufferance
Pure code-writing requests are off-topic on Stack Overflow -- we expect questions here to relate to specific programming problems -- but we will happily help you write it yourself! Tell us what you've tried, and where you are stuck. This will also help us answer your question better.Buss
Is also posible using the :active pseudoclass, but for exactly click event you need javascriptDarlenadarlene
it is possible using inputs and :checked pseudoclass. what have you tried so far ? example codepen.io/gcyrillus/pen/dsvwF that shows behavior with focus and checked pickup the one that seems the best fit to your needs and see what each method involves when in use ... and what is needed to stand in HTML code . both examples are accordion and very similar at first useBerk
another example using pointer-events codepen.io/gcyrillus/pen/pyjrjP also accordion ... So what css method have you tried so far ? :focus , :target, :checked, pointer-events, else ?Berk
@MikeMcCaughan Majorly updated that guy's question, wondering if you would consider this a proper question now?Sufferance
No, because it still doesn't show any attempt at actually making it work. It also doesn't have the code here on Stack Overflow. The article linked in my comment, How to Ask, says what we need under "Help others reproduce the problem": *If it is possible to create a live example of the problem that you can link to (for example, on sqlfiddle.com or jsbin.com) then do so - but also include the code in your question itself. Not everyone can access external sites, and the links may break over time. *Buss
see picocss dropdown menu and picocss nested hamburger menuCocks
D
27

Here you are using a hidden checkbox, and showing the menu when it is "checked".

/*hide the inputs/checkmarks and submenu*/
input, ul.submenu {
  display: none;
}

/*position the label*/
label {
  position: relative;
  display: block;
  cursor: pointer;
}

/*show the submenu when input is checked*/
input:checked~ul.submenu {
  display: block;
}
<input id="check01" type="checkbox" name="menu" />
<label for="check01">Menu</label>
<ul class="submenu">
  <li><a href="#">Item 1</a></li>
  <li><a href="#">Item 2</a></li>
</ul>

Taken from this Codepen and simplified.

Dogwatch answered 29/6, 2017 at 18:37 Comment(4)
This is brilliant! Shame it doesn't close when clicking outside the menu.Hadrian
@JanneAnnala see my update, however not sure how this works in the wild so make sure you test it!Dogwatch
Thanks! I tested a similar approach, but unfortunately that doesn't work because the focus is lost on mousedown, but the link gets opened on mouseup so the menu is gone before the mouseup triggers and no link is opened.Hadrian
welp, i guess this is what you get when you don't really do it the normal way. Very brilliant though, using a checkbox!Katha
M
11

Can. Example 1. Dropdown menu. Pure CSS. Simple style.
jsfiddle link

body {
  margin: 0;
  font-size: 20px;
  font-family: Times, "Times New Roman", serif;
}

/* dd container */
.dropdown {
  display: inline-block;
  position: relative;
  outline: none;
  margin: 10px;
}

/* button */
.dropbtn {
  padding: 12px 16px;
  color: white;
  background-color: #861cb9;
  cursor: pointer;
  transition: 0.35s ease-out;
}

/* dd content */
.dropdown .dropdown-content {
  position: absolute;
  top: 50%;
  background-color: #f7f7f7;
  min-width: 120%;
  box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.2);
  z-index: 100000;
  visibility: hidden;
  opacity: 0;
  transition: 0.35s ease-out;
}
.dropdown-content a {
  color: black;
  padding: 12px 16px;
  display: block;
  text-decoration: none;
  transition: 0.35s ease-out;
}
.dropdown-content a:hover {
  background-color: #eaeaea;
}

/* show dd content */
.dropdown:focus .dropdown-content {
  outline: none;
  transform: translateY(20px);
  visibility: visible;
  opacity: 1;
}
.dropbtn:hover, .dropdown:focus .dropbtn {
  background-color: #691692;
}

/* mask to close menu by clicking on the button */
.dropdown .db2 {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0; opacity: 0;
  cursor: pointer;
  z-index: 10;
  display: none;
}
.dropdown:focus .db2 {
  display: inline-block;
}
.dropdown .db2:focus .dropdown-content {
  outline: none;
  visibility: hidden;
  opacity: 0;
}
<div class="dropdown" tabindex="1">
  <i class="db2" tabindex="1"></i>
  <a class="dropbtn">Dropdown 1</a>
   <div class="dropdown-content">
      <a href="#">Home</a>
      <a href="#">About</a>
      <a href="#">Contact</a>
   </div>
</div>

<div class="dropdown" tabindex="1">
  <i class="db2" tabindex="1"></i>
  <a class="dropbtn">Dropdown 2</a>
   <div class="dropdown-content">
      <a href="#">Blog</a>
      <a href="#">Plans</a>
      <a href="#">Partners</a>
   </div>
</div>

Example 2. With added styles. Pure CSS. Without JS. Dropdown menu/content opens and closes on click. Several ways to close (by the same button, by another button, by clicking outside the menu area, by an icon inside the menu). Additionally added submenu by :hover.
jsfiddle link

body {
  margin: 0;
  font-size: 20px;
  font-family: Times, "Times New Roman", serif;
}

/* dd container */
.dropdown {
  display: inline-block;
  position: relative;
  outline: none;
  background-color: #861cb9;
  margin: 10px 5px;
}

/* button */
.dropbtn {
  display: inline-block;
  padding: 12px 16px;
  color: white;
  cursor: pointer;
  background-color: #861cb9;
  transition: 0.35s ease-out;
}
.dropbtn:hover, .dropbtn.c:hover, .dropbtn.r:hover {
  background-color: #691692;
}

/* dd content */
.dropdown .dropdown-content {
  position: absolute;
  top: 50%;
  visibility: hidden;
  opacity: 0;
  z-index: 100000;
  background-color: #f7f7f7;
  min-width: 120%;
  padding: 10px;
  font-size: 16px;
  box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.2);
  transition: 0.35s ease-out;
}

/* center & right position menu relative to the button */
.dropdown .dropdown-content.c  {
  left: 50%;
  margin-left: calc(-60% - 10px);
}
.dropdown .dropdown-content.r  {
  right: 0;
}

/* style link menu item */
.dropdown-content .mi {
  display: block;
  color: black;
  padding: 8px 0;
  text-decoration: none;
  position: relative;
}
.dropdown-content .mi::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background:
  linear-gradient(
  90deg,
  rgba(240, 242, 244, 0) 0%,
  rgba(223, 223, 223, 1) 30%,
  rgba(240, 242, 244, 0) 100%
  );
  opacity: 0;
  z-index: -1;
  transition: 0.4s ease-out;
}
.dropdown-content .mi:hover::before {
    opacity: 1;
}

/* style text link */
.dropdown-content .tl {
  color: #36f;
  text-decoration: none;
  border-bottom: 1px dotted #36f;
  transition: 0.35s ease-out;
}
.dropdown-content .tl:hover {
  border-bottom: 1px dotted transparent;
}

/* show dd content */
.dropdown:focus .dropdown-content {
  outline: none;
  visibility: visible;
  opacity: 1;
  transform: translateY(20px);
}

/* mask to close menu by clicking on the button */
.dropdown .db2 {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 10;
  display: none;
}
.dropdown:focus .db2 {
  display: inline-block;
}
.dropdown .db2:focus .dropdown-content, .dropdown-content .db3:focus .dropdown-content {
  outline: none;
  visibility: hidden;
  opacity: 0;
}

/* button gradient */
.dropbtn::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: -1;
  background: radial-gradient(circle at 0 0, #fff 0%, #D59BF0 5%, #8b1dc0 35%, transparent 60%);
  background-repeat: no-repeat;
  background-color: #861cb9;
  transition: 0.35s ease-out;
}

/* class 'c' center gradient backlight */
.dropbtn.c::before {
  background: radial-gradient(circle at 50% -1px, #fff 0%, #D59BF0 5%, #8b1dc0 35%, transparent 60%);
  background-repeat: no-repeat;
  background-color: #861cb9;
}

/* class 'r' right gradient backlight */
.dropbtn.r::before {
  background: radial-gradient(circle at 100% 0, #fff 0%, #D59BF0 5%, #8b1dc0 35%, transparent 60%);
  background-repeat: no-repeat;
  background-color: #861cb9;
}

/* show gradient backlight */
.dropdown:focus .dropbtn::before, .dropdown:focus .dropbtn.c::before, .dropdown:focus .dropbtn.r::before {
background-color: #691692;
}
.dropdown:focus  {
z-index: 1;
}
.dropdown:focus .dropbtn  {
background: none;
}

/* icon hamburger */
.dropbtn::after {
  content: "";
  display: inline-block;
  width: 15px;
  height: 3px;
  margin-left: 10px;
  border-top: 2px solid #fff;
  border-bottom: 7px double #fff;
}
.dropdown:focus .dropbtn::after {
  height: 0;
  border-bottom: 0;
  margin-bottom: 4px;
}

/* icon content */
.dropbtn.i2::after {
  content: "";
  display: inline-block;
  border: 0;
  width: 15px;
  height: 12px;
  margin-left: 10px;
  background:
  linear-gradient(to right, #fff, #fff) 0px 0px/11px 2px, /* left top / width height */
  linear-gradient(to right, #fff, #fff) 0px 5px/15px 2px,
  linear-gradient(to right, #fff, #fff) 0px 10px/8px 2px;
  background-repeat: no-repeat;
}
.dropdown:focus .dropbtn.i2::after {
  width: 15px;
  height: 12px;
  background: linear-gradient(to right, #fff, #fff) 0px 10px/15px 2px;
  background-repeat: no-repeat;
}

/* icon x */
.dropdown-content .db3  {
  display: inline-block;
  position: absolute;
  top: 5px;
  right: 5px;
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: 100%;
  z-index: 10;
  transition: 0.15s ease-out;
}
.dropdown-content .db3::before, .dropdown-content .db3::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  height: 60%;           /* height icon */
  width: 2px;            /* width icon  */
  background: #3c4043;   /* color icon  */
}
.dropdown-content .db3::before {
  transform: translate(-50%, -50%) rotate(45deg);
}
.dropdown-content .db3::after  {
  transform: translate(-50%, -50%) rotate(-45deg);
}
.dropdown-content .db3:hover   {
  background: #d1d1d6;
}

/* sub menu container */
.sub-dropdown {
  position: relative;
}
.sub-dropdown-content {
  position: absolute;
  visibility: hidden;
  opacity: 0;
  background-color: #f7f7f7;
  left: 100%;
  top: -10px;
  padding: 10px 5px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
  transition: 0.35s ease-out;
}
.sub-dropdown-content a {
  color: black;
  padding: 5px 12px;
  text-decoration: none;
  display: block;
  position: relative;
  white-space: nowrap;
}

/* sub menu item */
.si {
  cursor: default;
}
.si::after {
  content: "\25B8";
  margin-left: 5px;
  vertical-align: -1px;
  margin-right: 10px;
  float: right;
}
.sub-dropdown:hover .sub-dropdown-content {
  visibility: visible;
  opacity: 1;
  transform: translateY(10px);
}
.sub-dropdown-content a::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background:
  linear-gradient(
  90deg,
  rgba(240, 242, 244, 0) 0%,
  rgba(223, 223, 223, 1) 50%,
  rgba(240, 242, 244, 0) 100%
  );
  opacity: 0;
  z-index: -1;
  transition: 0.4s ease-out;
}
.sub-dropdown-content a:hover::before {
    opacity: 1;
}

/* media queries */
@media (max-width:560px) {
.dropdown .dropdown-content.r,
.dropdown .dropdown-content.c {
  left: 0;
  margin-left: 0;
  }
.dropbtn.c::before, .dropbtn.r::before {
  background: radial-gradient(circle at 0 0, #fff 0%, #D59BF0 5%, #8b1dc0 35%, transparent 60%);
  }
}
<div class="dropdown" tabindex="1">
  <i class="db2" tabindex="1"></i><a class="dropbtn i2">Dropdown l</a>
    <div class="dropdown-content"><i class="db3" tabindex="1"></i>
      <p>Dropdown content. Left-aligned relative to the button. Text <a href="#" class="tl">link</a> ....</p>
    </div>
</div>

<div class="dropdown" tabindex="1">
  <i class="db2" tabindex="1"></i><a class="dropbtn c">MyMenu c</a>
    <div class="dropdown-content c"><i class="db3" tabindex="1"></i>
      <a href="#" class="mi">Products</a>

      <div class="sub-dropdown">
      <a class="mi si">Company</a>
          <div class="sub-dropdown-content">
            <a href="#">Sublink 1</a>
            <a href="#">Sublink 2</a>
          </div>
      </div>

      <a href="#" class="mi">Stackoverflow</a>
    </div>
</div>

<div class="dropdown" tabindex="1">
  <i class="db2" tabindex="1"></i><a class="dropbtn r i2">Dropdown r</a>
    <div class="dropdown-content r"><i class="db3" tabindex="1"></i>
      <p>Dropdown content. Right-aligned relative to the button. Text <a href="#" class="tl">link</a> ....</p>
    </div>
</div>
Moriahmoriarty answered 8/2, 2022 at 7:21 Comment(2)
A masterpiece that deserves more upvotes. But what are the <i> elements for?Polydactyl
1. i class="db2". This is an invisible button-mask. So that a repeated click on the menu button closes the menu. 2. i class="db3". It's a close cross button inside the menu.Moriahmoriarty
S
8

Use radio buttons and sibling selectors.

This differs from checkboxes in that it will automatically close the open menu item when a different one is clicked.

.menu ul,
.menu input,
.menu .closer,
.menu input:checked~.opener {
  display: none;
}

.menu input:checked~ul,
.menu input:checked~.closer {
  display: block;
}
<ul class="menu">
  <li>
    <input type="radio" name="menuopt" id="drop1" />
    <label class="opener" for="drop1">Parent item 1</label>
    <label class="closer" for="dropclose">Parent item 1</label>
    <ul>
      <li><a href="">Menu item 1</a></li>
      <li><a href="">Menu item 2</a></li>
      <li><a href="">Menu item 3</a></li>
    </ul>
  </li>
  <li>
    <input type="radio" name="menuopt" id="drop2" />
    <label class="opener" for="drop2">Parent item 2</label>
    <label class="closer" for="dropclose">Parent item 2</label>
    <ul>
      <li><a href="">Menu item 1</a></li>
      <li><a href="">Menu item 2</a></li>
      <li><a href="">Menu item 3</a></li>
      <li><a href="">Menu item 4</a></li>
      <li><a href="">Menu item 5</a></li>
    </ul>
    <input type="radio" name="menuopt" id="dropclose" />
  </li>
</ul>

View on jsFiddle

Sufferance answered 29/6, 2017 at 18:50 Comment(0)
T
1

Here's the best and super simple implementaion that you can find

.dropbtn {
  padding: 8px 12px;
  background-color: DodgerBlue;
}
   
.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
}

.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

.dropbtn:focus + .dropdown-content {
  display: block;
}

.dropbtn:focus-outside + .dropdown-content {
  display: none;
}
<!-- When clicked outside the button, dropdown closes. This was generally not possible without javascript, but i did the trick ;) . We can also use multiple buttons like this with the same existing css styles. -->

<div class="dropdown">
  <button class="dropbtn">Dropdown</button>
  <div id="myDropdown" class="dropdown-content">
    <a href="#home">Home</a>
    <a href="#about">About</a>
    <a href="#contact">Contact</a>
  </div>
</div>

<div class="dropdown">
  <button class="dropbtn">Dropdown</button>
  <div id="myDropdown" class="dropdown-content">
    <a href="#home">Home</a>
    <a href="#about">About</a>
    <a href="#contact">Contact</a>
  </div>
</div>
Therrien answered 29/4, 2024 at 16:40 Comment(1)
Sweet!! Nice work!!Rhomb

© 2022 - 2025 — McMap. All rights reserved.