RE

Styling

React · 6 entries

Inline Styles

syntax
<div style={{ cssProperty: value }} />
example
function AlertBanner({ type, message }) {
  const styles = {
    padding: '12px 16px',
    borderRadius: '6px',
    fontWeight: 'bold',
    backgroundColor: type === 'error' ? '#fde8e8' : '#e8f5e9',
    color: type === 'error' ? '#c62828' : '#2e7d32',
    border: `1px solid ${type === 'error' ? '#ef9a9a' : '#a5d6a7'}`,
  };

  return <div style={styles}>{message}</div>;
}

Note Inline styles use camelCase property names and string/number values. They cannot handle pseudo-classes (:hover), media queries, or keyframe animations. Best for truly dynamic values that change at runtime.

CSS Modules

syntax
import styles from './Component.module.css';
<div className={styles.container} />
example
// Button.module.css
// .button { padding: 8px 16px; border-radius: 4px; }
// .primary { background: #1976d2; color: white; }
// .secondary { background: #e0e0e0; color: #333; }

import styles from './Button.module.css';

function Button({ variant = 'primary', children, ...rest }) {
  const className = `${styles.button} ${styles[variant]}`;

  return (
    <button className={className} {...rest}>
      {children}
    </button>
  );
}

Note CSS Modules scope class names locally by default, preventing naming collisions. The imported styles object maps your authored class names to unique generated ones. Supported out of the box by most React build tools.

className Patterns

syntax
<div className="static-class" />
<div className={dynamicVariable} />
<div className={`base ${condition ? 'active' : ''}`} />
example
function NavLink({ href, isActive, children }) {
  // Template literal approach
  const className = `nav-link ${isActive ? 'nav-link--active' : ''}`;

  return <a href={href} className={className}>{children}</a>;
}

// Helper function for multiple conditional classes
function classNames(...classes) {
  return classes.filter(Boolean).join(' ');
}

function Card({ featured, compact, className }) {
  return (
    <div
      className={classNames(
        'card',
        featured && 'card--featured',
        compact && 'card--compact',
        className
      )}
    >
      {/* ... */}
    </div>
  );
}

Note Use a small classNames helper or the popular 'clsx' package to compose conditional classes cleanly. Avoid complex ternary chains inside className attributes -- extract the logic to keep JSX readable.

Conditional Classes

syntax
// With clsx or classnames library
import clsx from 'clsx';
<div className={clsx('base', { active: isActive, disabled: isDisabled })} />
example
// Using the clsx library
import clsx from 'clsx';

function StatusChip({ status }) {
  return (
    <span
      className={clsx('chip', {
        'chip--success': status === 'active',
        'chip--warning': status === 'pending',
        'chip--danger': status === 'error',
        'chip--muted': status === 'inactive',
      })}
    >
      {status}
    </span>
  );
}

// Without a library
function StatusChipManual({ status }) {
  const chipClass = [
    'chip',
    status === 'active' && 'chip--success',
    status === 'error' && 'chip--danger',
  ].filter(Boolean).join(' ');

  return <span className={chipClass}>{status}</span>;
}

Note The clsx library (or classnames) accepts strings, objects, and arrays. Object keys are included when their value is truthy. It is lightweight (~228 bytes) and widely used in the React ecosystem.

CSS-in-JS Patterns

syntax
// styled-components / Emotion example pattern
const StyledButton = styled.button`
  background: ${props => props.primary ? 'blue' : 'gray'};
  color: white;
`;
example
// Using a CSS-in-JS library (styled-components pattern)
import styled from 'styled-components';

const Container = styled.div`
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
`;

const Title = styled.h1`
  font-size: ${props => props.large ? '2.5rem' : '1.5rem'};
  color: ${props => props.muted ? '#888' : '#111'};
  margin-bottom: 16px;
`;

function ArticlePage({ article }) {
  return (
    <Container>
      <Title large>{article.title}</Title>
      <p>{article.body}</p>
    </Container>
  );
}

Note CSS-in-JS co-locates styles with components and supports dynamic props, theming, and automatic vendor prefixing. The tradeoff is runtime overhead and larger bundle size. Consider CSS Modules or Tailwind for better performance in critical paths.

Utility-First CSS (Tailwind Pattern)

syntax
<div className="flex items-center gap-4 p-4 bg-white rounded-lg shadow" />
example
function UserCard({ user }) {
  return (
    <div className="flex items-center gap-4 p-4 bg-white rounded-lg shadow-sm border">
      <img
        src={user.avatarUrl}
        alt={user.name}
        className="w-12 h-12 rounded-full object-cover"
      />
      <div>
        <h3 className="font-semibold text-gray-900">{user.name}</h3>
        <p className="text-sm text-gray-500">{user.role}</p>
      </div>
      <span
        className={`ml-auto px-2 py-1 text-xs rounded-full ${
          user.active
            ? 'bg-green-100 text-green-800'
            : 'bg-gray-100 text-gray-600'
        }`}
      >
        {user.active ? 'Active' : 'Offline'}
      </span>
    </div>
  );
}

Note Utility-first CSS like Tailwind works well with React's component model -- styles are scoped per component by nature. Use clsx for conditional classes. Extract repeated patterns into components rather than creating custom CSS utility classes.