Property

@grid

The grid dimensions, and in the same line the size, background, gap, scale, rotation, border and more of the component.

Syntax

  • @grid: 5x5
  • @grid: 5x5 / 60vmin
  • @grid: 5x5 / 60vmin / #96c
  • @grid: 5x5 / 60vmin _4px dashed #000
  • @grid: 5x5 / 60vmin _4px +1.2 *20deg

The dimensions come first, then any number of modifiers in any order. Each modifier is a symbol followed by its value, which may contain spaces. Flags are single words and may appear anywhere.

ModifierSetsApplied to
/ <size>width and height, as @size:doodle
/ <fill>the second /: background:doodle
_ <gap>gap and optional rule, as @gap:container
+ <scale>scale:container
* <rotate>rotate:container
*h <angle>filter: hue-rotate():doodle
~ <translate>translate:container
^ <enlarge>width and height:container
∆ <perspective>perspective and perspective-origin:doodle
ß <border>border:doodle
| <filter>backdrop-filter on a layer above the cells:doodle
FlagEffect
rowflexbox layout, cells in a row
colflexbox layout, cells in a column
p3dtransform-style: preserve-3d
noclipcontain: none, cells may overflow the component

Every modifier is a shortcut: the equivalent CSS on :doodle or :container always works too.

Dimensions

n x m is columns by rows, from 1 to 64 each. A single number makes a square grid. See the grid attribute for the limits.

@grid: 3;

/* same as */
@grid: 3x3;

Size /

The first / sets the width and height of the component. A single value is used for both.

@grid: 4x4 / 60vmin;
background: #000;
margin: 1px;

/* / 60vmin equals */
:doodle {
  width: 60vmin;
  height: 60vmin;
}

When one of the two is auto the component gets an aspect-ratio matching the grid, columns / rows:

@grid: 5x4 / 60vmin auto;
background: #000;
margin: 1px;

/* / 60vmin auto equals */
:doodle {
  width: 60vmin;
  height: auto;
  aspect-ratio: 5 / 4;
}

A third value in parentheses sets the ratio explicitly:

@grid: 3x5 / 60vmin auto (5/4);
background: #000;
margin: 1px;

Background /

A second / sets the background of the component, with any value the CSS property accepts.

@grid: 4 / 60vmin / #000;
@grid: 4 / 60vmin / linear-gradient(#96c, #f9c);
@grid: 1 / 60vmin / @svg(
  viewBox: -5 -5 10 10;
  circle { r: 3; fill: #000 }
);

/* / #000 equals */
:doodle {
  background: #000;
}

Gap _

One or two lengths, like the CSS gap property. The space after _ is optional. Values after the lengths draw a rule inside the gap — the same writing as @gap.

@grid: 4 / 60vmin _10px 2px;
background: #000;

/* _10px 2px equals */
:container {
  gap: 10px 2px;
}

The gap rule is optional.

@grid: 5 / 60vmin _1px dashed #000;
background: #000;

Scale +

@grid: 8 / 60vmin _2px +1.2;
background: #000;

/* +1.2 equals */
:container {
  scale: 1.2;
}

Rotation *

An angle in deg, rad or turn; a bare number is degrees. Prefix the angle with x, y or z to rotate around one axis.

@grid: 5 / 60vmin ß1 _2px *15deg;
background: #000;

/* *15deg equals */
:container {
  rotate: 15deg;
}
@grid: 5 / 60vmin _2px *y 65deg;
background: #000;

/* *y 65deg equals */
:container {
  rotate: y 65deg;
}

Hue rotation *h

*h applies hue-rotate() to the whole component instead of rotating it.

@grid: 5 / 60vmin _2px *h 45deg;
background: #e6437d;

/* *h 45deg equals */
:doodle {
  filter: hue-rotate(45deg);
}

Translate ~

@grid: 5 / 60vmin ß1 _2px ~ 20% 20%;
background: #000;

/* ~ 20% 20% equals */
:container {
  translate: 20% 20%;
}

Enlarge ^

Changes the width and height of the container rather than scaling it, so font sizes and borders inside are not affected. A bare number is a ratio, a length is added to 100%. Two values set width and height separately.

@grid: 8 / 60vmin _1px ^1.2;
background: #000;

/* ^1.2 equals */
:container {
  width: calc(1.2 * 100%);
  height: calc(1.2 * 100%);
}
@grid: 8 / 60vmin _1px ^-30px;
background: #000;

/* ^-30px equals */
:container {
  width: calc(-30px + 100%);
  height: calc(-30px + 100%);
}

Perspective

A perspective distance, optionally followed by a perspective-origin.

@grid: 5 / 60vmin ß1 _1px *x 45 200px;
background: #000;

/* ∆ 200px equals */
:doodle {
  perspective: 200px;
}
@grid: 5 / 60vmin ß1 _1px *x 45 200px 100% 0;
background: #000;

/* ∆ 200px 100% 0 equals */
:doodle {
  perspective: 200px;
  perspective-origin: 100% 0;
}

Border ß

A border shorthand with lenient parsing: a bare number is pixels, a missing style is solid, and a lone color gets a 1px width.

@grid: 1 / 60vmin ß8;
@grid: 1 / 60vmin ß 1em;
@grid: 1 / 60vmin ß red;
@grid: 1 / 60vmin ß 8px dashed #000;

/* ß8 equals */
:doodle {
  border: 8px solid;
}

Backdrop filter |

Puts a layer above the cells with the given backdrop-filter. It combines well with @svg-filter.

@grid: 4 / 60vmin ^.85 _10px | @svg-filter(.015, 50);
border-radius: 50%;
background: #000;
@grid: 6 / 60vmin _4px | blur(3px) contrast(20);
background: #000;
border-radius: 50%;
scale: @r(.5, 1.2);

Flex layout row, col

The flags switch the container from grid to flexbox, and give every cell flex: 1.

@grid: col 4 / 60vmin _2px;
background: #000;
flex: @i;

/* col equals */
:container {
  display: flex;
  flex-direction: column;
}
@grid: row 6 / 60vmin _2px;
background: #000;
flex: @r(1, 3);

Preserve 3D p3d

@grid: 1x12 / 60vmin p3d;
:container {
  rotate: y @t(*.05deg);
}
@place: center;
@size: 80%;
border: 2px solid #000;
border-radius: 50%;
background: #fff;
rotate: y @iI(*360deg);

/* p3d equals */
:doodle, :container {
  transform-style: preserve-3d;
}

Containment noclip

By default the component clips its content. noclip lets cells overflow.

@grid: 1 / 60vmin ß1 noclip;
@size: 2em;
margin: -1em 0 0 -1em;
background: #000b;
:doodle {
  scale: .85;
}

/* noclip equals */
:doodle {
  contain: none;
}

See also