DEV Community

SEN LLC
SEN LLC

Posted on

A CSS Property Reference With 72 Live Previews — Click a Value, See It Apply

A CSS Property Reference With 72 Live Previews — Click a Value, See It Apply

MDN is the canonical CSS reference, but you have to read sentences. This one has a mini preview box for every property — click flex, grid, or block on the display property, and three demo divs rearrange in real time. 72 properties across 6 categories, bilingual descriptions.

Learning CSS from text is harder than it needs to be. flex-direction: column-reverse reads like arbitrary words; seeing three boxes flip their stacking order the instant you click the value is different. Interactive references are fundamentally more effective — if only they existed for CSS.

🔗 Live demo: https://sen.ltd/portfolio/css-props-ref/
📦 GitHub: https://github.com/sen-ltd/css-props-ref

Screenshot

Features:

  • 72 CSS properties in 6 categories
  • Live preview per property (click a value, see it apply)
  • Search by name or keyword
  • Category filter (Layout, Box Model, Typography, Color, Effects, Transform)
  • Bilingual Japanese / English descriptions
  • Dark / light theme
  • Zero dependencies, 38 tests

The 6 categories

  • Layout (20 props): display, position, flex-direction, justify-content, align-items, gap, grid-template-columns, grid-template-rows, place-items, flex-grow, flex-shrink, align-self, order, grid-column, grid-row, ...
  • Box Model (10): margin, padding, border, border-radius, width, height, min/max width/height, box-sizing
  • Typography (11): font-family, font-size, font-weight, line-height, letter-spacing, text-align, text-decoration, text-transform, white-space, word-break, text-overflow
  • Color (8): color, background-color, background-image, background-size, background-position, opacity, backdrop-filter, mix-blend-mode
  • Effects (8): box-shadow, filter, clip-path, overflow, visibility, cursor, pointer-events, user-select
  • Transform (15): transform, rotate, scale, translate, transform-origin, transition, animation, animation-timing-function, ...

The data model

Each property has a name, valid values, description, and a preview config:

{
  name: 'display',
  category: 'layout',
  values: ['block', 'inline', 'inline-block', 'flex', 'grid', 'none'],
  description: {
    ja: '要素の表示タイプを指定',
    en: 'Sets the display type of an element',
  },
  preview: {
    html: '<div class="container"><div class="box">A</div><div class="box">B</div><div class="box">C</div></div>',
    target: '.container',
  },
}
Enter fullscreen mode Exit fullscreen mode

The target selector specifies which element inside the preview HTML gets the dynamic style. Clicking a value rewrites the style on that element.

Live preview via scoped style injection

Applying CSS to a preview without leaking styles across the page means scoping via a generated class and a dynamic <style> tag:

function renderPreview(card, prop, value) {
  const id = `preview-${prop.name}`;
  const scope = `[data-preview-id="${id}"]`;
  const css = `${scope} ${prop.preview.target} { ${prop.name}: ${value}; }`;

  let style = card.querySelector('style');
  if (!style) {
    style = document.createElement('style');
    card.appendChild(style);
  }
  style.textContent = css;
}
Enter fullscreen mode Exit fullscreen mode

Each preview card has a unique data-preview-id attribute. The generated CSS is scoped to that attribute, so display: flex on one property card doesn't affect the next one.

Pseudo-elements via :before

Properties like content can only be applied to ::before / ::after. The scoped style approach still works — you just generate a selector with ::before appended:

const selector = prop.name === 'content' ? '.target::before' : '.target';
const css = `${scope} ${selector} { ${prop.name}: ${value}; }`;
Enter fullscreen mode Exit fullscreen mode

Search with language-aware matching

export function searchProps(query, lang = 'en') {
  const q = query.toLowerCase();
  return PROPS.filter(p =>
    p.name.includes(q) ||
    p.description[lang].toLowerCase().includes(q) ||
    p.values.some(v => v.includes(q))
  );
}
Enter fullscreen mode Exit fullscreen mode

Typing "flex" finds display, flex-direction, flex-grow, flex-shrink, justify-content (since "flex-start" is a value). Typing the Japanese "中央" matches text-align (center → 中央) via the description field.

Series

This is entry #73 in my 100+ public portfolio series.

Top comments (0)