Understand CSS Variables and Animations by Building A pimped up And Responsive Navbar

Understand CSS Variables and Animations by Building A pimped up And Responsive Navbar

CSS variables are widely used by the web masters to perform tricks that amaze everybody. Let's learn what it is and how to use it.

Featured on Hashnode

Variables

Variables are essential part of programming languages and most recently cascading style sheets (CSS). These variables are used to store information to be referenced and manipulated in a computer program. They also provide a way of labeling data with a descriptive name, so our programs can be understood more clearly by the reader and ourselves.

What are CSS Variables

CSS variables also known as custom properties are entities defined by CSS authors that contain specific values to be reused throughout a document. They are set using custom property notation (e.g., --bg-color-light: ash;) and are accessed using the var() function (e.g., background-color: var( --bg-color-light);).

CSS variables are very essential for use in a large websites that require the usage of the same property value through out the site. For instance, a particular duration might be used to handle animations through out a site and if the duration needs to be changed, the change will only be performed at the variable set in the global state.

CSS variables can be set globally inside the :root selector so that it can be accessed by every element of the HTML document. It can also be scoped locally inside a particular element using a class, id or other CSS selectors. Also, they are case sensitive meaning that site-color is different from site-Color. For this example, I set different background color for each button by using variables such as style="--bgColorItem: #f54888". This variables would be used in the style.css to set the background-color for each button( or .menu__items).

Here is an example of a basic usage of CSS variables:

Note: CSS variables values can be changed in an HTML or JavaScript file.

Building Out The Navbar skeleton

To build the navbar, our codebase will consist of an HTML, CSS and script file.

In the HTML file, we will create an element with class of .wrapper that wraps the whole app. It will contain two elements: nav and a div. The nav will contain five buttons. The button will contain a svg element.The div element will contain it's own svg tag too.

In the CSS file, it will contain a basic styling to show the svg and its container in it's most crooked way.

Here is the skeleton codes:

Styling the Navbar

.wrapper style

We will begin with the wrapper class by adding a transition to handle the background-color change. You can style the wrapper the way you want.

.wrapper {
  background-color: #ffb457;
  -webkit-tap-highlight-color: transparent;

  /* Styling */
  transition: background-color var(--duration);
  display: flex;
  justify-content: center;
  padding: 6em 0;
}

.icon style

The next step is to set the style of the icon. The styles would give the icons the shapes they will take for the rest of the project.

.icon {
  /* Helps view the icon */
  width: 2.6em;
  height: 2.6em;
  stroke: white;
  /* End of help */

  /* Beautification styling */
  stroke-width: 0.1em;
  stroke-dasharray: 400;
  stroke-miterlimit: 10;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* End of Beautification styling */
}

.menu style

The .menu class is used to grab the nav tag which is essentially all the button container. We will also set the media query for smaller screens.

We will make use of the --bgColorMenu variable in the :root selector to style the background color.

.menu {
  width: 32.05em;
  font-size: 1.5em;
  background-color: var(--bgColorMenu);

  display: flex;
  justify-content: center;
  padding: 0 2.85em;
  position: relative;
}

@media screen and (max-width: 50em) {
  .menu {
    font-size: 0.8em;
  }
}

.menu__item style

The .menu__item selects the button. Here, we first of all unset every possible css property using the all: unset property. We also use the timeOut variable just to toggle the value of the transform from undefined to the duration specified. It somewhat acts like a memory cleanup for the navbar.

We also style the pseudo element before it so we can toggle the transition property with Javascript. This essentially sets the round underlay on the button.

We also style the active element by moving it up a bit using the transform: translateY() property and value. The active class background color is set to a scoped color set on the each button. Check the HTML file to see the colors set in its style.

The smooth animation of the icons is handled using the stroker keyframes by using the stroke-dashoffset property.


.menu__item {
  /* "all" resets every property of an element and requires you to set each property yourself */
  all: unset;
  flex-grow: 1;
  z-index: 1;
  position: relative;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0.55em 0 0.85em;
  border-radius: 50%;
  /* The var inside a var is used as a kind of if statement. If the first isn't available, it uses the second one and vice versa  */
  transition: transform var(--timeOut, var(--duration));

  will-change: transform;
}

.menu__item::before {
  content: "";
  position: absolute;
  z-index: -1;
  width: 4.4em;
  height: 4.4em;
  border-radius: 50%;
  transform: scale(0);

  /* You can combine two or more properties in transition */
  transition: background-color var(--duration), transform var(--duration);
}

.menu__item.active {
  /* This and the transition above handles the movement of the active button  */
  transform: translateY(-0.8em);
}

.menu__item.active::before {
  transform: scale(1);

  /* This handles the changing color of active button */
  background-color: var(--bgColorItem);
}
/* This handles movement of the icons from left to right */
.menu__item.active .icon {
  /* The reverse direction offers a smother experience */
  animation: stroker 1.5s reverse;
}

@keyframes stroker {
  100% {
    stroke-dashoffset: 400;
  }
}

menu__border style

The menu__border essentially appears over the icon on press or click. We will toggle it's current position using JavaScript but for the moment, let's give it a default position.

We begin by grabbing the svg using the #menu id set in the HTML. Next, we set it's position to absolute and the .svg-container to a height and width of zero.


.menu__border {
  /* Access the svg using id from the html */
  clip-path: url(#menu);

  position: absolute;
  left: 0;
  bottom: 99%;

  /* Handle size of svg in with id menu */
  width: 10.9em;
  height: 2.7em;
  background-color: var(--bgColorMenu);
  transition: transform var(--timeOut, var(--duration));
  will-change: transform;
}

.svg-container {
  width: 0;
  height: 0;
}

The full styling should look like this:

Add The Toggle Functionality

We are done with the essential styling but the buttons do not respond on click. To make them work, we use Javascript.

Grab The DOM Elements

The first step is to grab all the elements we want using querySelector or querySelectorAll and specify the background colors to be used in an array:

const wrapper = document.querySelector(".wrapper");
const menu = document.querySelector(".menu");
const menuItems = document.querySelectorAll(".menu__item");
const menuBorder = document.querySelector(".menu__border");
let activeItem = document.querySelector(".active");

const backgroundColors = [
  "#ffb457",
  "#ff96bd",
  "#9999fb",
  "#ffe797",
  "#cffff1",
];

Create the handleClick function

The handleClick functions takes in an item and index parameters. It is the entry point to the whole Navbar toggling.

function handleClick(item, index) {

  if (item === activeItem) return;

  if (activeItem) {
    activeItem.classList.remove("active");
  }

  item.classList.add("active");
  wrapper.style.backgroundColor = backgroundColors[index];
  activeItem = item;
}
`

Add Click Event Listener to the Menu Items

This is achieved by iterating through the nodelist provided by the querySelectorAll when grabbing the .menu__item elements.

menuItems.forEach((item, index) => {
  item.addEventListener("click", () => handleClick(item, index));
});

Handle Position of the Menu Border

We can achieve this by creating a function that takes the activeItem and menuBorder. Then we use the activeItem width, left distance, the menuBorder offsetWidth and the menu offsetLeft to transform the menuBorder by translateX().

Handle Animations on window resize

To achieve this we listen to the resize event on the window like this:

window.addEventListener("resize", () => {
  handleBorderPosition(activeItem, menuBorder);
});

Enable Synced behavior between menuBorder and activeItem backgroundColor

To do this, set the property of --timeOut to none like this: menu.style.setProperty("--timeOut", "none");, in the resize eventListener.

Also, remove the property timeOut at the topmost part of the handleClick function like this: menu.style.removeProperty("--timeOut");

The final product should look similar to this:

Conclusion

To conclude, the CSS variable is a very powerful aspect of CSS that can be used to create very powerful animations and beautiful interfaces based on user preferences such as themes. We need opportuinity to use it the more to get very exciting and amazing results.

Shout Outs and Appreciations:

Designed by: Mauricio Bucardo

Original image: dribbble.com/shots/5619509-Animated-Tab-Bar