You Don't Need JavaScript for That!

Cristina Silva

I often use a few CSS alternatives to common JavaScript interactions when I’m developing the front-end of a website (especially a prototype). There are some projects where downloading a plugin or creating a new file for a few lines of code seems like overkill. Here are some components I use created by using only CSS:

Tooltips

Tooltips are great for showing helpful information that isn’t necessary to a user’s experience. There are a few JavaScript plugins that give us this behavior, but if you don’t feel like adding that weight to your site, we can take care of it with plain ol’ CSS.

We can use pseudo-elements to pull in text and display it on :hover. (You could use the HTML title attribute to effectively accomplish the same solution, but you can’t style the tooltip to your liking.)

HTML:


<a href="#" class="tooltip-toggle" aria-label="Sample text for your tooltip!" tabindex="0">
  Label for your tooltip
</a>

SCSS:


.tooltip-toggle {
  cursor: pointer;
  position: relative;

  //Tooltip text container - above element
  //You can adjust the position to make the container appear below or beside the element
  &::before {
    background-color: #000;
    border-radius: 5px;
    color: #fff;
    content: attr(aria-label); //This pulls in the text from the element with the tooltip
    left: -80px; //This centers the container above the element
    padding: 1rem;
    position: absolute;
    text-transform: none;
    top: -80px; //This places the container above the element that needs a tooltip
    transition: all 0.5s ease;
    width: 160px;
  }

  //Tooltip arrow
  //You can adjust the position of this to align nicely with the element that
  //needs a tooltip. You can also use `transform` to rotate it to make the
  //tooltip work below or next to the element.
  &::after {
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 5px solid #000;
    content: " ";
    font-size: 0;
    left: 9px; //This centers the arrow above the element with the tooltip
    line-height: 0;
    margin-left: -5px;
    position: absolute;
    top: -12px; //This positions the arrow at the bottom of the container
    width: 0;
  }

  //Setting up the transition
  &::before,
  &::after {
    opacity: 0;
    pointer-events: none;
  }

  //Triggering the transition
  &:focus::before,
  &:focus::after,
  &:hover::before,
  &:hover::after {
    opacity: 1;
    transition: all 0.75s ease;
  }
}

View on Codepen

If you need to implement a simple dropdown menu, you can use CSS to easily trigger the visibility of the menu on :hover.

HTML:


<div class="nav-container">
  <ul class="nav-items">
    <!-- Navigation -->
    <li class="nav-item"><a href="#">Home</a></li>
    <li class="nav-item"><a href="#">About</a></li>
    <li class="nav-item"><a href="#">Contact</a></li>

    <!-- Dropdown menu -->
    <li class="nav-item nav-item-dropdown">
      <a class="dropdown-trigger" href="#">Settings</a>
      <ul class="dropdown-menu">
        <li class="dropdown-menu-item">
          <a href="#">Dropdown Item 1</a>
        </li>
        <li class="dropdown-menu-item">
          <a href="#">Dropdown Item 2</a>
        </li>
        <li class="dropdown-menu-item">
          <a href="#">Dropdown Item 3</a>
        </li>
      </ul>
    </li>
  </ul>
</div>

SCSS:


//Nav bar styling
.nav-container {
  background-color: #fff;
  display: block;
  margin: 0 auto;
  max-width: 400px;
  padding: 1em;
  text-align: center;
}

ul,
li {
  list-style: none;
  -webkit-padding-start: 0;
}

//Navigation menu
.nav-item {
  display: inline;
  padding: 1em;
}

//Dropdown menu
.nav-item-dropdown {
  position: relative;

  &:hover > .dropdown-menu {
    display: block;
    opacity: 1;
  }
}

.dropdown-trigger {
  position: relative;

  &:focus + .dropdown-menu {
    display: block;
    opacity: 1;
  }

  &::after {
    color: #ED3E44;
    content: "›";
    font-size: 24px;
    font-weight: bold;
    position: absolute;
    right: -15px;
    top: -5px;
    transform: rotate(90deg);
  }
}

.dropdown-menu {
  background-color: #fff;
  display: inline-block;
  display: none;
  opacity: 0;
  position: absolute;
  right: -10px;
  text-align: right;
  top: 2.5rem;
  transition: opacity 0.5s ease;
  width: 160px;
}

.dropdown-menu-item {
  cursor: pointer;
  padding: 1em;
  text-align: center;

  &:hover {
    background-color: #ccc;
  }
}

View on Codepen

Toggle Visibility

The most common reason I turn to JavaScript is to toggle the visibility of an element. I recently learned that you can use the :checked pseudo-class to change the CSS of an element. (Thanks, Charlotte Jackson!)

HTML:


<div class="toggle">
  <!-- Checkbox toggle -->
  <input type="checkbox" value="selected" id="beethoven-joke" class="toggle-input">
  <label for="beethoven-joke" class="toggle-label">What was Beethoven's favorite fruit?</label>

  <!-- Content to toggle -->
  <div role="toggle" class="toggle-content">
    BA-NA-NA-NA!
 </div>
</div>

SCSS:


.toggle {
  margin: 0 auto;
  max-width: 400px;
}

//Style toggle
.toggle-label {
  background: #fff;
  cursor: pointer;
  display: block;
  font-size: 16px;
  margin: 0 auto 1em;
  padding: 1em;

  &:after {
    content: "+";
    float: right;
  }
}

//Style content
.toggle-content {
  padding: 1em;
}

.toggle-input {
  display: none; //Hide input element

  &:not(checked) ~ .toggle-content {
    display: none; //Hide content
  }
}

//Display content when checkbox is "checked"
.toggle-input:checked {
  ~ .toggle-content {
    display: block;
  }

  ~ .toggle-label {
    &:after {
      content: "-"; //Change label's '+' to '-' when checked
    }
  }
}

View on Codepen

In the end…

To recap, here’s a few reasons why using CSS over JavaScript can be beneficial to your project:

  • Lightweight, no need to install a plugin or add another .js file
  • Clarity around what’s happening with styles and transitions
  • Keep things simple and get things built quickly

And for good measure, here’s a few reasons to seek alternatives to these CSS-only methods:

  • Accessibility concerns - a lot of these components need some JavaScript love to be more accessibility friendly. For more information about web accessibility, check out the WCAG Guidelines
  • Support for touch devices - :hover can’t help you on a phone, so seek alternatives for accessing this content on a mobile device
  • JavaScript can help you accomplish a more well-rounded feature

Every project has different needs, so make sure you’re picking solutions that work best for your project’s goals. No single solution will work for all projects. In the meantime, it’s great to see what CSS can accomplish on its own.