No history yet

State Based Styling

Styling with States

As designers, we often think about how an element should look in different situations. A button isn't just a button; it can be active, disabled, or hovered over. A menu can be open or closed. Each of these variations is a 'state,' a specific condition that an element can be in.

Instead of telling JavaScript exactly how to change an element's style, we can simply tell it to change the element's state. JavaScript's job is to manage when the state changes, while CSS handles how each state looks. This clean division of labor is a core web development principle called Separation of Concerns().

Introduce the concept of separation of concerns - HTML for structure, CSS for presentation, JavaScript for behavior.

Triggering State Changes

The most common way to change an element's state is with a user action, like a click. We use an event listener() to wait for that action and then run some code. In this case, the code will change the element's class.

Let's imagine we have a navigation menu. In our CSS, we define how it looks by default, and also how it looks when it has an is-open class.

/* Default state: menu is hidden */
.nav-menu {
  display: none;
  background-color: #f1f1f1;
  padding: 20px;
}

/* Open state: menu is visible */
.nav-menu.is-open {
  display: block;
}

Our JavaScript doesn't need to know about display: block or display: none. It only needs to know about the is-open class. When a button is clicked, it adds or removes that class from the menu.

// Find the button and the menu
const menuButton = document.querySelector('#menu-toggle');
const navMenu = document.querySelector('.nav-menu');

// When the button is clicked...
menuButton.addEventListener('click', () => {
  // ...add or remove the 'is-open' class on the menu.
  navMenu.classList.toggle('is-open');
});

The classList.toggle() method is perfect for this. It checks if the class exists. If it does, it removes it. If it doesn't, it adds it. It's a switch for your styles.

Smooth Transitions

This state-based approach works beautifully with CSS transitions. Instead of the menu just appearing and disappearing, we can make it fade in or slide down smoothly. The JavaScript doesn't change at all. We just update our CSS.

.nav-menu {
  opacity: 0;
  transform: translateY(-20px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.nav-menu.is-open {
  opacity: 1;
  transform: translateY(0);
}

Now, when classList.toggle('is-open') runs, the browser sees that the opacity and transform properties are changing. Because we have a transition defined, it animates the change automatically over 0.3 seconds. JavaScript handles the logic, and CSS handles the presentation, including the animation. Each technology does what it does best.

Quiz Questions 1/4

According to the principle of "Separation of Concerns," what is the primary role of JavaScript when managing an element's state?

Quiz Questions 2/4

A developer has a menu that opens and closes by toggling the .is-open class. They now want to make the menu fade in smoothly instead of just appearing. Where should they make this change?

By thinking in states, you create a more organized and maintainable system. Your JavaScript becomes simpler because it's only managing classes, and your CSS contains all the design logic, right where it belongs.