Advertisement

Expandable News Card Widget

| by Vladimir | 2 min read | code by Shahid Shaikh
Beginner

Tech & Dependencies

Babel CSS HTML
React react-dom

Features

  • State-Driven Expansion
  • CSS Transitions
  • Gradient UI
  • Class Component

Browser Support

Chrome 100+ Edge 100+ Safari 14+ Firefox 90+

Core

This Expandable News Card Widget demonstrates a classic pattern for managing content density in UI design. By default, it presents a single “Headline” state to save screen space. Upon interaction, it smoothly transitions into an “Expanded” state, revealing a scrollable list of news items. It utilizes React state to handle the logic and CSS transitions for the visual effect.

Core Technique

The component relies on toggling a CSS class based on the component’s internal state, allowing CSS to handle the heavy lifting of the animation.

1. State-Driven Class Toggling

The component is built as a React Class Component. It initializes a state object with open: false. The handleClick method toggles this boolean. In the render method, a ternary operator conditionally appends the "expand" class to the container.

// Toggling logic inside render()
<div
  className={"container " + (this.state.open ? "expand" : "")}
  onClick={this.handleClick}
>
  {/* Content... */}
</div>

2. CSS Height Transition

The animation is achieved purely through CSS. The base .container class has a fixed height of 200px and a transition property set to animate all changes over 300ms. When the .expand class is added by React, it overrides the height property.

.container {
  /* Initial compacted state */
  height: 200px;
  overflow: hidden; /* Hides the lower content */
  transition: all 300ms ease-in-out;
}

div.expand {
  /* Expanded state triggered by React */
  height: 797px; 
}

Note: Using a fixed pixel height (797px) in the expanded state is a “magic number” technique. For dynamic content, developers often use JavaScript to calculate the scrollHeight.

Accessibility (A11y)

The component uses a div with an onClick handler, which presents significant barriers:

  • Keyboard Navigation: The div is not focusable, meaning keyboard users cannot tab to it or activate it with Enter/Space.
  • Semantics: Screen readers interpret it as a generic container, not an interactive button.
  • State Feedback: There is no aria-expanded attribute to inform assistive technology of the current state.

Fix: Change the container to a <button> or add role="button", tabIndex="0", and aria-expanded={this.state.open}.

Browser Support

The snippet uses standard CSS transitions and React, ensuring broad compatibility.

Advertisement