BerlinX Component guide
Semantic CSSv1.0.0

BerlinX

Thoughtful defaults.
Beautifully simple.

Build clear, considered interfaces with the HTML you already know. One stylesheet, native components, and room for your own design.

Classless · CSS only · Light and dark · MIT licensed


Installation

Add the stylesheet to your page. Semantic elements get considered defaults; attributes give you variants when you need them.

<link rel="stylesheet" href="./berlinx.min.css" />

Download the stylesheet · Installation & theming guide

Light and dark themes follow the reader’s system setting. Add theme="light" or theme="dark" to <html> to choose one, or to any container to theme just that region. Try the moon button to switch this page.


Preview

A little inspiration, occasionally.

Design notes, useful patterns, and new releases. A quiet corner of your inbox, with something worth opening.


Typography

Good typography makes an interface feel effortless. A restrained scale, comfortable line lengths, and deliberate spacing help people find what matters and read without distraction.

The details should support the content. Give every element enough space to be understood, and every page a clear place to begin.
A principle behind BerlinX

Lists

Inline text elements

Link

Bold

Italic

Underline

Deleted

Inserted

Strikethrough

Small

Text Sub

Text Sup

Abbr.

inline code

Ctrl + C

Highlighted

Primary and accent text

Heading 3

Integer bibendum malesuada libero vel eleifend. Fusce iaculis turpis ipsum, at efficitur sem scelerisque vel. Aliquam auctor diam ut purus cursus fringilla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

Heading 4

Cras fermentum velit vitae auctor aliquet. Nunc non congue urna, at blandit nibh. Donec ac fermentum felis. Vivamus tincidunt arcu ut lacus hendrerit, eget mattis dui finibus.

Heading 5

Donec nec egestas nulla. Sed varius placerat felis eu suscipit. Mauris maximus ante in consequat luctus. Morbi euismod sagittis efficitur. Aenean non eros orci. Vivamus ut diam sem.

Heading 6

Ut sed quam non mauris placerat consequat vitae id risus. Vestibulum tincidunt nulla ut tortor posuere, vitae malesuada tortor molestie. Sed nec interdum dolor. Vestibulum id auctor nisi, a efficitur sem. Aliquam sollicitudin efficitur turpis, sollicitudin hendrerit ligula semper id. Nunc risus felis, egestas eu tristique eget, convallis in velit.


Accordions

Terms & Conditions

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque urna diam, tincidunt nec porta sed, auctor id velit. Etiam venenatis nisl ut orci consequat, vitae tempus quam commodo. Nulla non mauris ipsum. Aliquam eu posuere orci. Nulla convallis lectus rutrum quam hendrerit, in facilisis elit sollicitudin. Mauris pulvinar pulvinar mi, dictum tristique elit auctor quis. Maecenas ac ipsum ultrices, porta turpis sit amet, congue turpis.


Badge

Primary Secondary Outline Destructive Link

badge works on any inline element. kbd is a keycap, not a badge.



Buttons

Variants are attributes rather than input types, so they compose freely with behaviour — <button type="submit" destructive> both submits and reads as dangerous, and any variant can hold an icon.


Card

A place for your next idea

Bring the brief, the details, and the next step together. A simple card gives related content a clear home without competing for attention.

A semantic article, styled automatically.

Checkbox


Dialog

Confirm your action

Cras sit amet maximus risus. Pellentesque sodales odio sit amet augue finibus pellentesque. Nullam finibus risus non semper euismod.


Drawer

Confirm your action!

Cras sit amet maximus risus. Pellentesque sodales odio sit amet augue finibus pellentesque. Nullam finibus risus non semper euismod.

Confirm your action!

Cras sit amet maximus risus. Pellentesque sodales odio sit amet augue finibus pellentesque.

drawer anchors to the bottom; drawer="top|left|right" anchors to any other edge.


Form

Submit defaults to primary and reset to outline, from the element's own semantics. A reset button no longer looks like a delete button.


Group

Checkboxes

Input


Labels

A label is a row: its text sits beside the control, and a text control takes the rest of the line. stack turns it into a field instead, with the label above a full-width control.


Layout

ClientBook

Edit client details

Ada Lovelace ada@example.com
All changes saved

row and col pick the axis, gap-xs / gap-s / gap-m / gap-l size the space between children, and justify and items place them along the axis and across it. Headings and paragraphs drop their block margins inside a row, since the container is already spacing its children with gap. grid fit makes the form two columns when there is room and one on a phone. grow gives the title the space left beside the account button; nowrap keeps that header on one line. Use full-width when a button should fill its container.


Feedback

Your changes are being synced.

The client was saved successfully.

Your trial ends in 3 days. Add a payment method to keep your projects.

The connection was interrupted. Please try again.

notice styles the message; notice="success", "warning" and "error" add a coloured edge. Choose role="status" for updates or role="alert" for urgent errors when adding messages dynamically.


Control density

Compact — toolbars and desktop apps
Comfortable — forms and touch screens

Set density="compact" or density="comfortable" on a container to size its controls together. A label tag wraps a real, keyboard-accessible file input; visually-hidden keeps it available to assistive technology.


Loading

loading draws the spinner; aria-busy="true" carries the meaning. Use both. aria-busy is a true/false state, so it cannot be a styling hook on its own. On a button, link or summary the spinner replaces the icon rather than sitting next to it. With reduced motion enabled, the spinner keeps turning gently while decorative animations stop. Add disabled to a busy button to prevent keyboard activation.




Popover

Simple popover

Dimensions

Set the dimensions for the layer.

Signed in as ada@example.com

A popover opens centred above its anchor. placement moves it: top or bottom, on their own or with -start / -end to line its edge up with the anchor's. Anchored placement is progressive enhancement — engines without CSS anchor positioning centre the popover in the viewport instead, and where it is supported a popover near an edge flips to the other side rather than opening off-screen. The layout attributes work inside one: this menu is a col gap. Use placement="center" for a viewport-centred popover.


Progress bar


Radio Group


Scroll Area

Scroll horizontally →Room for wider content
Scroll vertically ↓You have reached the end.

Focus either region to scroll with the keyboard, or use a trackpad or touch gesture.


Select


Separator

Radix Primitives An open-source UI component library.


Blog
Docs
Source


Slider


Switch


Table

Table caption
Person Most interest in Age
Chris HTML tables 22
Dennis Web accessibility 45
Sarah JavaScript frameworks 29
Karen Web performance 36
Average age 33

Responsive

Person Most interest in Age
Chris HTML tables 22
Dennis Web accessibility 45

responsive gives a too-wide table its own horizontal scrollbar so it can never stretch the page; pair it with white-space: nowrap if you want the columns to keep their natural width instead of cramming. Prefer it on a wrapper — <div responsive> — because on the table itself it has to switch the table to a block box, which makes the columns shrink to their content. responsive="stack" instead breaks each row into its own card under 600px, printing every cell's data-label beside its value — narrow the window to see it. Both drop the table role where they change display; put role="table", role="row" and role="cell" back if screen-reader users need the grid.

Row actions

Person Most interest in
Chris HTML tables
Dennis Web accessibility

reveal on the row keeps its controls out of the way until you point at it — hover a row, or tab into one, and they appear. Where the pointer cannot hover they are never hidden. tooltip names an icon-only button on hover and focus, but it is drawn in CSS and assistive tech never sees it, so the aria-label beside it is doing the real work.


Tag

Primary Secondary Outline Ghost Destructive Link

tag gives any element the button's exact appearance and every button variant — they share the same rules, so they cannot drift apart. Only a tag that is an a, button, summary or label gets the hand cursor and the hover, active and focus states; a plain <span tag> never pretends to be clickable.


Textarea


Toast

Scheduled: Catch up
Friday, February 10, 2023 at 5:57 PM

Toggles

The wrapping label toggle makes the icon clickable and keyboard-operable natively — no JavaScript.


Field validation

We will send your receipt here. Enter an email address, such as name@example.com.
This username is already taken.

field groups a label, control and descriptions. In a validation form, native :user-invalid reveals the error after interaction; aria-invalid="true" supports errors supplied by your application. Keep descriptions connected with aria-describedby.


Segmented controls

Billing period

fieldset segmented styles real radio buttons. Tab into the group and use the arrow keys to change selection.


Selectable cards

Choose a plan

label choice highlights its native checked or focused input. Radio cards select one option; checkbox cards allow independent choices.


Rich lists

ul list or ol list aligns row content and actions. A single anchor can make a whole row a link. Keep role="list" when removing native list markers.


Description lists

Client
Katherine Johnson
Email
katherine@example.com
Plan
Team Monthly
Notes
Prefers email updates. Next review is scheduled for November.

Plain dl, dt and dd create a responsive label/value layout. Optional div wrappers can group each pair. On phones the values sit below their labels.


Pagination

Page 1 of 3 · Ada Lovelace

nav pagination styles page links and aria-current="page". Your application supplies page URLs and current state; this preview changes the sample record locally. An unavailable page is a span or a disabled button, rather than a clickable disabled-looking link.


Avatars

AL GH KJ
ALGHKJ

avatar works on an image or an element containing initials. Use small, large or --avatar-size to change its size. avatars overlaps a group. Supply image alt text or an accessible name for initials.


Empty states

No projects yet

Choose a plan and give your next idea a place to grow.

Explore plans

empty groups an illustration, heading, explanation and action. Your application decides when to show it.


Steps

  1. Account completedYour profile is ready
  2. Choose a planFind the right fit
  3. Start a projectInvite your team

ol steps presents progress supplied in the markup. Mark finished steps with complete and the current one with aria-current="step". It stacks vertically on phones.


Timeline

  1. Project created

    Ada opened the autumn planning workspace.

  2. Team invited

    Grace and Katherine joined the project.

  3. First milestone reached

    The project brief is ready for review.


Meters

Use a native meter for a measurement within a known range, such as a quota. Use progress for work being completed. Native low, high and optimum define the value ranges.


Ratings

How was your experience?

fieldset rating keeps native radio semantics, arrow-key navigation and form values. The stars up to the selected value are filled using CSS.


Notification indicators

ALAvailable
3 unread notifications
  • Grace joined your team
  • Your weekly report is ready
  • Project brief approved

indicator positions a badge or status dot on a control or avatar. Include the count or status in accessible text, not just the dot's colour.


Navigation tabs

Overview

A shared workspace for the autumn launch.

Activity

The team has completed the project brief.

Settings

Team plan · Monthly billing · Email notifications enabled.

nav tabs styles ordinary navigation links and aria-current. These links jump to sections; they retain link semantics. Content-switching ARIA tabs require additional focus and keyboard handling.