9

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>

8
  • Could possibly do with clever use of the focus event
    – Randy Hall
    Commented Jun 29, 2017 at 18:34
  • 1
    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. Commented Jun 29, 2017 at 18:35
  • Is also posible using the :active pseudoclass, but for exactly click event you need javascript
    – stalin
    Commented Jun 29, 2017 at 18:39
  • 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 use
    – G-Cyrillus
    Commented Jun 29, 2017 at 18:42
  • 8
    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. * Commented Jul 3, 2017 at 13:21

4 Answers 4

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.

4
  • This is brilliant! Shame it doesn't close when clicking outside the menu. Commented Nov 22, 2019 at 11:15
  • @JanneAnnala see my update, however not sure how this works in the wild so make sure you test it!
    – CalvT
    Commented Nov 25, 2019 at 17:15
  • 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. Commented Nov 26, 2019 at 18:15
  • welp, i guess this is what you get when you don't really do it the normal way. Very brilliant though, using a checkbox! Commented Jan 23, 2020 at 1:13
10

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>

2
  • A masterpiece that deserves more upvotes. But what are the <i> elements for?
    – Gaspa79
    Commented May 9, 2023 at 13:48
  • 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.
    – Arsen
    Commented May 12, 2023 at 5:19
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

0
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>

1
  • Sweet!! Nice work!!
    – Ole
    Commented Apr 29 at 19:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.