.ids

Intuition Design System, IDS — a design system for building landing pages, online publications, and any digital web products that are based on narratives.

Technically, IDS is a set of CSS classes and JS components. It’s not a library, but a ready-made layout template. You don’t include IDS in your project as a dependency, you don’t extend classes, you don’t override properties. Instead, you simply copy its source code and modify it however you like. No compatibility issues and no breaking updates.

IDS is distributed under the MIT license — you can use and modify it for free, no restrictions. We also don’t accept complaints, can’t provide guidance, and there’s no support service. If you’re interested but not sure how to work with it — welcome to the course “How to Design with Code”, it will help.

Setup

Basic design system parameters are set in the css/settings.css file.

Font

IDS uses the Inter font by default, the variable web version. It’s great! But the design system isn’t tied to a specific font — you can use any font. Just place the font files in the fonts folder and edit the Fonts section in the css/settings.css file. Please try not to pirate fonts.

Density

Different fonts suit different layout densities. Additionally, density is an aesthetic choice — sometimes you need tight layout, sometimes airy.

IDS has a variable --ids__density that affects text line-height, as well as margins and paddings of all text elements. To adjust layout density, first try to find the optimal value for this variable, then edit individual styles.

Responsiveness

IDS assumes there are only two types of devices: mobile and desktop. This is determined by viewport width (simplified: browser window width): less than 768 px means mobile, more means desktop.

IDS implements the Fluid Typography concept — where the font-size for the whole document (the html element) is calculated based on viewport width, and then em or rem units are used not only for text but also for margins, paddings, border radii, and sometimes element dimensions.

This approach simplifies design debugging. First, you need to find the optimal font-size range suitable for the chosen font and desired size of “regular” text.

This range is set by the variables --desktop-font-size-min and --desktop-font-size-max. You need to find values such that when the width changes, the text scales while preserving line breaks. Then you can check the layout at just one width, knowing that at any width the element arrangement will be preserved.

For mobile, you need to find your own pair of values --mobile-font-size-min and --mobile-font-size-max, but the idea is exactly the same — consistent layout on phones of different widths.

Color

Color in IDS lives in variables and is split into two layers.

The first layer is the palette, the css/tokens/palette.css file: raw color values with names like --ids__color-blue-500. The palette is theme-independent and is never used directly anywhere except the second layer.

white

rgb(255, 255, 255)

gray-100

rgb(238, 240, 242)

gray-200

rgb(220, 221, 223)

gray-400

rgb(153, 156, 160)

gray-500

rgb(115, 120, 125)

gray-600

rgb(85, 88, 92)

gray-700

rgb(55, 58, 62)

gray-800

rgb(32, 33, 36)

gray-900

rgb(18, 18, 20)

gray-950

rgb(5, 5, 5)

blue-450

rgb(60, 130, 250)

blue-500

rgb(0, 100, 240)

green-450

rgb(40, 215, 40)

green-500

rgb(0, 200, 0)

green-600

rgb(30, 170, 60)

red-450

rgb(255, 70, 95)

red-500

rgb(253, 47, 75)

yellow-500

rgb(255, 225, 0)

The second layer is semantic colors, the css/tokens/colors.css file: naming is functional, named after what it’s used for. Each semantic color references the palette. The dark theme is just a different set of references to the same palette: each tile is labeled with the palette color the token references in the current theme.

text

gray-950gray-200

link

blue-500blue-450

hover

green-500green-450

mark

yellow-500

code

gray-500gray-400

text-caption

gray-600gray-400

accent

red-500red-450

surface

gray-100gray-800

background

whitegray-900

Only semantic colors are used in layout. Semi-transparent variants are not stored in variables — they are derived in place with color-mix.

Not like this

color: var(--ids__accent-50);

But like this

color: var(--ids__accent);

color: color-mix(in srgb, var(--ids__accent) 50%, transparent);

Page frame

IDS doesn’t use modular grids or columns for page space organization. It’s simpler: the page consists of “floors” that go from top to bottom one after another, each takes up the full available width and can be any height. This approach doesn’t prevent creating modular grids and complex compositions inside a floor, but the isolation of floors allows easily rearranging them and eliminates any interdependency.

Wrappers

.ids__wrapper — standard floor with large margins on desktop and minimal on mobile.

.ids__wrapper.L — floor with increased width. Different only on desktop, on mobile it matches the standard.

.ids__wrapper.XL — full-width floor with minimal margins. Different only on desktop, on mobile it matches the standard.

.ids__wrapper.XXL — full-width floor without margins, on mobile too.

For single-column text inside a standard floor, an additional wrapper is used that reduces the width and leaves extra margin on the right. This is only on desktop; on mobile, full width remains.

.ids__text-width

Vertical spacing system

In IDS, wrappers have zero margins, and most other elements have only a minimal bottom margin, to lay out elements in a continuous flow.

When noticeable spacing is needed — for example, between floors or before a heading so it doesn’t stick to the previous paragraph — special spacers are used.

ids__space.S

ids__space.M

ids__space.L

ids__space.XL

Tag styling

IDS styles some commonly used tags so you can lay out large volumes of text while keeping minimal markup. Tag styles are defined only inside the .ids container.

Here are the tags styled inside .ids.

Headings

h1

Main page heading


h2

Second level heading


h3

Third level heading


h4

Fourth level heading


h5
Fifth level heading

h6
Sixth level heading

Sometimes you don’t visually need headings as large as h1 or h2. But according to accessibility standards, the page must have an h1, and the next level must be h2, and so on, without gaps. To resolve this contradiction, we’ve prepared special classes that reduce h1 and h2:

h1.S

Main heading, reduced


h1.XS

Main heading, reduced even more


h2.XS

Second level heading, reduced


Sometimes you want to attach a label, tag, or badge above a heading. For this, the hgroup tag is used.

hgroup

p

h1

Heading label

Main page heading

Text

p

There’s never enough information for making decisions, by definition. When there’s enough information, the right move can be “calculated,” determined with high accuracy based on data, adding two and two. If there’s enough information — there’s nothing to decide.

p.loud

A designer should be independent, versatile, multidisciplinary, and complex.

p.huge

I changed my mind.

mark code

Used to highlight an important thought or a code fragment.

Illustration

figure figcaption

Photo by Mehmet Turgut Kirkgoz
Photo: Mehmet Turgut Kirkgoz

List

ul li

  • No,
  • no
  • and no.

ol li

  1. Basic level
  2. Functional level
  3. Empathic level

Link

a

.ids__promo-link

Pseudo-radio group for scroll navigation

Additional text

aside

Grid

Using the .ids__sequence class, you can quickly create a grid of identical elements, implemented via display: flex. Make .ids__sequence the parent, and wrap each grid cell in .ids__sequence-item:

.ids__sequence

.ids__sequence-item

.ids__sequence-item

Size modifier

ids__sequence.XL

Text in cell

Text in cell

ids__sequence.L

ids__sequence.S

Gap control

.ids__sequence.XL.gap-L

.ids__sequence.XL.gap-M

.ids__sequence.XL.gap-S

Table

table — regular table

tr, th, td — standard table elements. Well, except th sticks to the top of the window.

Components

.ids__sleepy

Component for animating element appearance on scroll. Tracks element visibility and removes the .is-sleeping class when more than 30% of the element is visible on screen.

The component automatically initializes for all elements with the .ids__sleepy class on page load. It only adds and removes the modifier class, nothing more.

Accordingly, for the animation to work, you need to

  • add the .ids__sleepy class to all elements that should animate when appearing on screen;
  • add the .is-sleeping modifier class definition to these elements with styles for the inactive state;
  • define the transition property to animate the changing properties.

ids-footnote

ids-footnote-link and ids-footnote — components for creating popup footnotes with automatic numbering.

The system consists of two parts: the trigger link (ids-footnote-link) and the container with footnote content (ids-footnote).

Usage example:

This is simple text with a first footnote and another second footnote for demonstration.

This is the content of the first footnote. It can include any markup: paragraphs, links, lists.

And this is the second footnote. Note that the number appears automatically.

A footnote can contain multiple paragraphs. If the content is too long and doesn’t fit on the screen, a “Close” button appears, and main page scrolling is blocked.

And here is a longer paragraph to show footnotes with two-digit numbers. A good footnote doesn’t interrupt reading — it complements it: it holds terms, sources, digressions and other details that don’t belong in the main text. Once a footnote number becomes two-digit, it no longer fits in the circle — and the badge stretches into a pill. You can see it on the tenth, eleventh and twelfth footnotes of this paragraph.

The third footnote: reading really wasn’t interrupted.

A term is a word or phrase that needs an explanation. For example, “footnote.”

A link to the original source could go here.

A digression is a thought too good to throw away, but one that breaks the rhythm of the main text.

Details are for those who read this far.

The eighth footnote is about the circle. Single-digit numbers fit in it entirely.

A pill is a rectangle with fully rounded ends. The ninth footnote is the last one in a circle.

The tenth footnote: the number no longer fits in the circle, so the badge became a pill.

The eleventh footnote — to check that the pill doesn’t fall apart.

The twelfth footnote. You can stop counting now.

The paragraph is over, and so are the footnotes.

Markup structure:

<p> Text with <ids-footnote-link>footnote link</ids-footnote-link> in the text. </p>

<ids-footnote> <p>Footnote content.</p> </ids-footnote>

ids-navbar

The component forms a group of links for scroll navigation from elements wrapped in the ids-nav-item tag. Required attributes:

  • id — unique heading identifier
  • label — link text

You can see an example of such a navbar in the top left corner of this page — the section navigation of this guide is built with it.

The menu doesn’t have to be fixed relative to the window: the component can be placed anywhere, including right in the text flow.

ids-gallery

Image gallery that opens and navigates in a modal window.

The src attribute of the img tag specifies a reduced thumbnail, and the href attribute of the a tag — the link to full size. (They can match if you don’t want to bother with thumbnails). If the full-size image is different, you need to specify its dimensions in the data-pswp-width and data-pswp-height attributes.

The content of figcaption is displayed under the preview in the grid and in the modal window when viewing.

Photo by Jan van der Wolf
Photo: Jan van der Wolf
Photo by Mehmet Turgut Kirkgoz
Photo: Mehmet Turgut Kirkgoz
Photo by Jan van der Wolf
Photo: Jan van der Wolf
Photo by Jan van der Wolf
Photo: Jan van der Wolf
Photo by Mehmet Turgut Kirkgoz
Photo: Mehmet Turgut Kirkgoz
abstract geometry
abstract geometry
abstract geometry
abstract geometry
abstract geometry
abstract geometry
abstract geometry
abstract geometry

.ids__inline-gallery

Gallery that switches with horizontal cursor movement (and swipe gesture on mobile). Built from a sequence of static images and used when you need controlled animation. Or whatever else you can think of.

The element takes the width of the parent container. Proportions are set explicitly via the --img-aspect-ratio variable in width / height format. These are the image proportions, not the entire element — it’s easiest to write the file dimensions in pixels there.

If image proportions differ from those set in the variable, images scale to fill the container (object-fit: cover) and are centered.

You can add a link, and then the entire element becomes clickable, and images on hover will have increased brightness.

There are current position indicators — numeric and two graphical variants.

.ids__rounded

Modifier for rounding corners not with a circle segment, but with a superellipse.

Photo by Jan van der Wolf
Photo by Jan van der Wolf
Photo by Jan van der Wolf

The rounding radius is set in the --ids__radius variable, which means it can be set both globally, for the entire document, and locally, for a specific section or element.

ids-gen-cover

Generative cover. The image is built deterministically from two numbers in the seed-a and seed-b attributes: the same seeds always produce the same picture. Tag content becomes a caption over the image.

On hover the color window shifts one palette step. Film grain sits on top (SVG noise, mix-blend-mode: overlay); turn it off with grain="off".

Palette

Intuition Design System