Selectors
:doodle
The :doodle
is a special selector indicates to the component element itself.
Note that the styles would be over-written by your normal CSS files outside.
(try to hover on the doodle)
:doodle {
@grid: 5 / 8em;
--s: 0;
gap: 1px;
}
:doodle(:hover) {
--s: 1;
}
--offset: calc(var(--s) * 100%);
transform: translateY(var(--offset));
transition: .5s cubic-bezier(.175, .885, .32, 1.275);
transition-delay: @rand(500ms);
transform-origin: 50% 50%;
background: #60569e;
:container
The :container
is the container element that holds all the cells, which is using Grid Layout.
You may want to set gap
inside it.
:doodle {
@grid: 8 / 8em;
overflow: hidden;
}
:container {
gap: 1px;
transform: rotate(45deg) scale(1.5);
}
background: #60569e;
It inherits all the grid properties from :doodle
so that's why this also works:
@nth(n, ...)
Select the nth cell like :nth-child(n)
does.
:doodle {
@size: 8em;
gap: 1px;
}
background: #f5f5f5;
:nth-child(1) {
background: #60569e;
}
@nth(5) {
background: #60569e;
}
@nth(3n + 8) {
background: #e6437d;
}
@nth(1, 5, 3n + 8) {
:after {
content: @index;
font-size: .8em;
color: #fff;
}
}
@even
Select cells like :nth-child(even)
but shorter.
:doodle {
@size: 8em;
}
@even {
background: #60569e;
:after {
content: @index;
font-size: .8em;
color: #fff;
}
}
@odd
Select cells like :nth-child(odd)
.
:doodle {
@size: 8em;
}
@odd {
background: #60569e;
:after {
content: @index;
font-size: .8em;
color: #fff;
}
}
@at(col, row)
Select cell at specific column and row.
:doodle {
@size: 8em;
gap: 1px;
}
background: #f5f5f5;
@at(4, 2) {
background: #60569e;
:after {
content: @x, @y;
font-size: .5em;
color: #fff;
}
}
@random([ ratio ])
Select cells randomly. The ratio
accepts value between 0
and 1
. Defaults to 0.5
.
:doodle {
@size: 8em;
gap: 1px;
}
background: #f5f5f5;
transition: .2s;
@random {
background: #60569e;
:after {
content: @index;
font-size: .8em;
color: #fff;
}
}
The selector can be applied multiple times.
:doodle {
@grid: 16 / 8em;
}
margin: -.5px;
@random {
border-top: 1px solid #60569e;
}
@random {
border-left: 1px solid #60569e;
}
@random(.2) {
:after {
content: '';
background: hsl(@rand(360), 60%, 70%);
@size: @rand(3px);
}
}
@row(n, ...)
Select the nth row of the grid.
:doodle {
@size: 8em;
}
background: #f5f5f5;
margin: .5px;
@row(3) {
background: #60569e;
:after {
content: @row;
font-size: .8em;
color: #fff;
}
}
The odd
and even
is supported.
:doodle {
@size: 8em;
}
background: #f5f5f5;
margin: .5px;
@row(even) {
background: #60569e;
:after {
content: @row;
font-size: .8em;
color: #fff;
}
}
@row(even) {
:after {
content: @row;
font-size: .8em;
color: #fff;
}
}
@col(n, ...)
Select the nth column of the grid.
:doodle {
@size: 8em;
}
background: #f5f5f5;
margin: .5px;
@col(3) {
background: #60569e;
:after {
content: @col;
font-size: .8em;
color: #fff;
}
}
You can use odd
and even
too.
:doodle {
@size: 8em;
}
background: #f5f5f5;
margin: .5px;
@col(odd) {
background: #60569e;
:after {
content: @col;
font-size: .8em;
color: #fff;
}
}
@match(expression)
Target the cells based on general Math expressions.
The variable
i
, I
,
x
, X
,
y
and Y
can be used without prefix @
symbol for calculation.
:doodle {
@size: 8em;
}
background: #f5f5f5;
margin: .5px;
@match(i <= 8 || i >= 18) {
background: #60569e;
:after {
content: @i;
font-size: .8em;
color: #fff;
}
}
For convenience the symbols ≤
and ≥
have the meanings of <=
and >=
respectively.
:doodle {
@size: 8em;
}
background: #f5f5f5;
margin: .5px;
@match(x ≤ y) {
background: #60569e;
}
The equal sign can be both =
and ==
.
:doodle {
@size: 8em;
}
background: #f5f5f5;
margin: .5px;
@match(x = y) {
background: #60569e;
}
@match(X-x+1 == y) {
background: #60569e;
}
A more complex example.
:doodle {
@size: 8em;
}
background: #f5f5f5;
@match(tan.cos.sin(x*y) > 1) {
background: #60569e;
}
Functions
@index
Returns the current index value of the cell.
:doodle {
@size: 8em;
}
background: #60569e;
margin: .5px;
:after {
content: @index;
color: #fff;
font-size: .8em;
}
The parentheses can be omitted if the function has no parameters.
@grid: 5x1 / 8em;
@place: center;
@size: calc(100% / @size() * @i);
z-index: calc(@size - @i);
opacity: calc(1.1 - 1 / @size * @i);
background: #60569e;
:after {
content: @index();
position: absolute;
top: .2em; right: .2em;
color: #fff;
font-size: .6em;
}
Alias: @i
@row
Returns the current row number of the cell.
:doodle {
@size: 8em;
}
background: #60569e;
margin: .5px;
:after {
content: @row;
color: #fff;
font-size: .8em;
}
Alias: @y
@col
Returns the current column number of the cell.
:doodle { @size: 8em; }
background: #60569e;
margin: .5px;
:after {
content: @col;
color: #fff;
font-size: .8em;
}
Alias: @x
@size-row
Returns the max row number of the grid.
@grid: 4x3 / 8em;
background: #60569e;
margin: .5px;
:after {
content: @row/@size-row;
color: #fff;
font-size: .8em;
}
Alias: @Y
@size-col
Returns the max column number of the grid.
@grid: 4x3 / 8em;
background: #60569e;
margin: .5px;
:after {
content: @col/@size-col;
color: #fff;
font-size: .8em;
}
Alias: @X
@size
Returns the total cells count of the grid.
@grid: 3 / 8em;
background: #60569e;
margin: .5px;
:after {
content: @i / @size;
color: #fff;
font-size: .8em;
}
These numbers can be used to generate dynamic values together with calc()
.
@grid: 5/8em;
--alpha: calc(@row * @col / @size);
background: rgba(96, 86, 158, var(--alpha));
:after {
content: @calc(@row * @col);
color: #fff;
font-size: .8em;
}
Alias: @I
@pick(v1, v2,...)
Randomly pick a value from the given list.
(try to click on the doodle)
:doodle { @size: 8em; }
opacity: @pick(1, .6, .3, .1);
background: #60569e;
:after {
content: @pick(1, 2, 3, 4);
color: #fff;
font-size: .8em;
}
It supports range format like this: [0-9a-z]
:doodle { @size: 8em; }
opacity: @pick(1, .6, .3, .1);
background: #60569e;
:after {
content: @pick([a-z]);
color: #fff;
font-size: .8em;
}
Alias: @p
@pick-n(v1, v2,...)
Pick a value from the given list one by one.
:doodle { @size: 8em; }
opacity: @pick-n(1, .6, .3, .1);
background: #60569e;
:after {
content: @pick-n([1-4]);
color: #fff;
font-size: .8em;
}
Alias: @pn
@pick-d(v1, v2,...)
Pick a value like @pick-n()
, but with distinct random order.
:doodle { @size: 8em; }
opacity: @pick-d(1, .6, .3, .1);
background: #60569e;
:after {
content: @pick-d([a-z]);
color: #fff;
font-size: .8em;
}
Alias: @pd
@rand(start [,end])
Returns a random value between two numbers.
(try to click the doodle)
:doodle { @size: 8em; }
background: rgba(96, 86, 158, @rand(.9));
transition: .2s ease @rand(200ms);
will-change: transform;
transform: rotate(@rand(360deg));
clip-path: polygon(
@rand(100%) 0, 100% @rand(100%), 0 @rand(100%)
);
Alias: @r
@last-pick, @last-rand
Returns the last value of @pick
, @pick-n
, @pick-d
and @rand
.
@grid: 5 / 8em;
background: linear-gradient(
@pick-d(45deg, -45deg),
@pick(#60569e, #e6437d),
rgba(255, 255, 255, 0),
@last-pick()
);
Alias: @lp
and @lr
, respectively.
@repeat(times, value)
Compose the given value multiple times.
(try to click the doodle)
:doodle { @size: 8em; gap: 1px }
background: #60569e;
transition: .2s;
transform: scale(.95);
border-radius: @repeat(4, @rand(40%, 60%));
:after {
content: '';
position: absolute;
transition: .2s;
left: @rand(20%, 80%);
top: @rand(20%, 80%);
@size: 5px;
border-radius: 50%;
background: #@repeat(6, @p([0-9a-f]));
}
Alias: @rep
@multiple(times, value)
Same as @repeat()
, but seperated with commas.
Use capitalized @Multiple
to make the values seperated with spaces.
:doodle {
@size: 8em;
}
background: linear-gradient(
@rand(360deg),
@m3(
@pick-n(#60569e, #e6437d, #ebbf4d)
calc(@n(-1) * 100% / 3),
@lp calc(@n * 100% / 3)
)
);
The number closely after the function name will be regarded as the first parameter of the function,
which will make the code more concise.
:doodle { @size: 8em; }
background: #60569e;
margin: 20%;
box-shadow: @m5(
calc(@n() * 2px) calc(@n * 2px) 0 0 #e6437d
);
Alias: @m
, @M
@n, @nx, @ny, @N
Used only inside @repeat
and @m
function to indicate the
current repeating count: @n
,
current column count: @nx
,
current row count: @ny
and the max count value: @N
.
:doodle {
@size: 8em;
}
background: radial-gradient(
circle at @r(100%) @r(100%),
@m20(
@p(#60569e, #ebbf4d)
calc(@n(-1) * 100% / @N),
@lp calc(@n * 100% / @N)
)
);
@stripe(color [size], ...)
Make stripe with gradients.
@grid: 5 / 8em;
background: linear-gradient(
@r(360deg),
@stripe(
#60569e, #e6437d, #ebbf4d
)
);
The size for each step is optional.
:doodle {
@size: 8em;
}
background: linear-gradient(
45deg,
@stripe(
#60569e 50%, #e6437d, #ebbf4d, #60569e
)
);
:doodle { @size: 8em; }
border-radius: 50%;
background: conic-gradient(
@stripe(
#60569e 10%,
#e6437d 20%,
#ebbf4d 30%,
#321f35
)
);
See more about
stripe function in css-doodle.
@svg-filter(filter)
Apply SVG filters.
@<Math>
All Math functions and constants are available prefixed with '@'
.
:doodle { @size: 8em; }
--alpha: calc(@abs(@abs(@row - 3) + @abs(@col - 3) - 5) / 5);
background: rgba(
96, 86, 158, var(--alpha)
);
will-change: transform;
transform: rotate(15deg) scale(var(--alpha));
You can also use π
directly.
@grid: 1x60 / 8em 15em;
@size: 65% 1px;
justify-self: center;
background: #60569e;
opacity: calc(1 - @i / @size());
transform:
rotate(-15deg)
translateX(calc(@sin(@i / 4) * π * 10px));
@calc(expr)
Evaluate calculations.
@grid: 5 / 8em;
background: #60569e;
:after {
content: @calc(@i * @i);
color: #fff;
font-size: .5em;
}
@odd {
transform: scale(.75);
}
@var(expr)
Same as native var()
. Used to prevent the browser from evaluating the value inside nested vars.
The example below won't work since the var(--bg)
has no definition outside.
Use @var()
instead.
:doodle {
@grid: 5 / 8em;
}
--bg: #60569e;
background: linear-gradient(
@r(360deg),
@var(--bg) 50%, #0000 0
);
@hex(num)
Transform a number into hex format.
:doodle { @size: 8em; gap: 1px }
:after {
content: \@hex(@rand(9632, 9687));
color: #60569e;
}
@doodle(code)
Generate url()
image with css-doodle code.
@grid: @p(2, 3) / 8em;
background-image: @doodle(
@grid: @r4 / 100%;
background: @doodle(
@grid: @r4 / 100%;
background: @svg(
viewBox: 0 0 1 1;
path {
d: M 0 0 L 1 0 L 1 1;
fill: #60569e;
}
);
);
);
See: https://yuanchuan.dev/whats-new-in-css-doodle
@shaders(code)
Generate url()
image with GLSL code. Currently only one uniform value is added: u_resolution
.
@grid: 1 / 8em;
background: @shaders(
void main() {
vec2 p = gl_FragCoord.xy / u_resolution.xy;
FragColor = vec4(p.yx, .8, 1.);
}
);
The function accepts three parts. If there's no explict fragment
part,
all the code will be treated as fragment shader like the example above.
Multiple texture are accepted if they prefix with texture
and
the texture uniform names will be injected automatically.
@grid: 1 / 8em;
background: @shaders(
texture1 {
@grid: 1 / 100%;
background: linear-gradient(
45deg,
@stripe.@m20.@p(#FFF4E0, #F8B501, #06ACB5, #17191D, #FC3D3C)
);
}
fragment {
void main() {
vec2 p = gl_FragCoord.xy / u_resolution.xy;
vec2 c = vec2(.5, .5);
vec2 uv = p.xy - c;
float R = 3.141593;
float len = length(uv * vec2(u_resolution.x / u_resolution.y, 1.));
float angle = atan(uv.y, uv.x) + R * smoothstep(.75, 0., len);
float r = length(uv) + .1;
vec2 coords = vec2(r * cos(angle), r * sin(angle)) + c;
FragColor = texture(texture1, coords);
}
}
);
See: https://yuanchuan.dev/add-shaders
@shape(commands)
Generate polygon()
in string used by clip-path
. For example, to make a hexagon:
@grid: 1 / 8em;
background: #60569e;
clip-path: @shape(
points: 6;
scale: .8;
);
If the points
value is big enough it approximately to be a circle.
@grid: 1 / 8em;
background: #60569e;
clip-path: @shape(
points: 100;
scale: .8;
);
All commands
fill-rule
nonzero | evenodd;
frame
number for frame size;
points
number between 3 - 3600;
rotate
number in degree for rotation;
scale
number for scale factor;
move
a pair of value for translating x, y
coords;
turn
the angle between start/end point, defaults to be 1;
x
x coordinate for cartesian equation;
y
y coordinate for cartesian equation;
r
polar equation;
Operations in equations
-
Operations available:
+
,
-
,
*
,
/
,
%
,
^
.
-
All JavaScript Math functions and constants are supported.
Such as
sin
,
cos
,
tan
,
abs
,
pow
,
PI
or π
etc.
@grid: 1 / 8em;
background: #60569e;
clip-path: @shape(
points: 300;
r: cos(4t);
scale: .8;
);
See more examples here: https://css-doodle.com/shapes.
@plot(commands)
Generate two values in percent and seperated with space.
The syntax is the same with @shape.
@grid: 1 / 8em;
background: @m50(
radial-gradient(#60569e 50%, #0000 0)
@plot(r: .8) / 5px 5px
no-repeat
);
@grid: 50x1 / 8em;
@size: 5px;
border-radius: 50%;
border: 1px solid #60569e;
@place: @plot(
r: sin(-t/2);
move: 0 -.3;
rotate: 90;
);