makeStyles
Is used to define styles, returns a React hook that should be called inside a component:
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
button: { color: 'red' },
icon: { paddingLeft: '5px' },
});
function Component() {
const classes = useClasses();
return (
<div>
<button className={classes.button} />
<span className={classes.icon} />
</div>
);
}
Nesting selectorβ
One of the promises of Atomic CSS is reducing the amount of styles, however more selectors are created when nested.
The &
character references the parent selector(s):
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
'& .foo': { color: 'green' },
'&.bar': { color: 'red' },
},
});
.f15f830o .foo {
color: green;
}
.fns74iw.bar {
color: red;
}
As in CSS spacing between &
and a selector matters, Whatβs the Difference?
Pseudo-classesβ
These rules are transformed to receive a nesting selector:
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
':active': { color: 'pink' },
':hover': { color: 'blue' },
// π‘ :link, :focus, etc. are also supported
':nth-child(2n)': { backgroundColor: '#fafafa' },
},
});
.fqsesyh:active {
color: pink;
}
.f10q6zxg:hover {
color: blue;
}
.fnbrw4x:nth-child(2n) {
background-color: #fafafa;
}
Pseudo-elementsβ
Griffel supports pseudo-elements like ::before
and ::after
.
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
'::after': {
content: '""', // Note the nested quotes
},
},
});
When setting content on pseudo elements, make sure to use nested quotes, e.g. content:Β '"hello"'
This also applies for empty content: content: '""'
.
:global()
selectorβ
Another useful feature is :global()
selector, it associates local styles with global selectors.
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
':global(html[data-whatintent="mouse"])': { backgroundColor: 'yellow' },
},
});
html[data-whatintent='mouse'] .f1xz3i88 {
background-color: yellow;
}
At-rulesβ
@media
, @container
, @supports
& @layer
queries are also supported:
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
'@media screen and (max-width: 992px)': { color: 'orange' },
'@container (max-width: 992px)': { color: 'orange' },
'@container foo (max-width: 992px)': { color: 'orange' },
'@supports (display: grid)': { color: 'red' },
'@layer utility': { marginBottom: '1em' },
},
});
@media screen and (max-width: 992px) {
.f5d6c3d {
color: orange;
}
}
@container (max-width: 992px) {
.xx {
color: orange;
}
}
@container foo (max-width: 992px) {
.xx {
color: orange;
}
}
@supports (display: grid) {
.f1ofq0jl {
color: red;
}
}
@layer utility {
.f2d3jla {
margin-bottom: 1em;
}
}
@keyframes
(animations)β
keyframes
are supported via animationName
property that can be defined as an object:
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
animationIterationCount: 'infinite',
animationDuration: '3s',
animationName: {
from: { transform: 'rotate(0deg)' },
to: { transform: 'rotate(360deg)' },
},
},
});
.f1cpbl36 {
animation-iteration-count: infinite;
}
.f1a27w2r {
animation-duration: 3s;
}
.f1g6ul6r {
animation-name: f1q8eu9e;
}
@keyframes f1q8eu9e {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
animationName
can be also an array of styles objects:
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
asArray: {
animationIterationCount: 'infinite',
animationDuration: '3s',
animationName: [
{
from: { transform: 'rotate(0deg)' },
to: { transform: 'rotate(360deg)' },
},
{
from: { height: '100px' },
to: { height: '200px' },
},
],
},
});
Using RESET
β
You can set RESET
value to remove a property (it won't generate a CSS rule unlike initial
or unset
):
import { makeStyles, mergeClasses, RESET } from '@griffel/react';
const useClassesA = makeStyles({
root: {
color: 'red',
backgroundColor: 'blue',
},
});
const useClassesB = makeStyles({
root: {
color: RESET,
},
});
function Component() {
const classesA = useClassesA();
const classesB = useClassesB();
// π‘ After merging, the `color` property will be removed
const className = mergeClasses(classesA.root, classesB.root);
// π‘ If `RESET` value is set, it won't be added to the class
return <div className={classesA} />;
}
CSS Fallback Propertiesβ
Griffel supports CSS fallback properties in order to support older browsers.
Any CSS property accepts an array of values which are all added to the styles. Every browser will use the latest valid value (which might be a different one in different browsers, based on supported CSS in that browser):
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
overflowY: ['scroll', 'overlay'],
},
});
.f1qdoogn {
overflow-y: scroll; /* Fallback for browsers which do not support overflow: overlay */
overflow-y: overlay; /* Used by browsers which support overflow: overlay */
}
RTL supportβ
Griffel uses rtl-css-js to perform automatic flipping of properties and values in Right-To-Left (RTL) text direction defined by TextDirectionProvider
.
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
paddingLeft: '10px',
},
});
/* Will be applied in LTR */
.frdkuqy {
padding-left: 10px;
}
/* Will be applied in RTL */
.f81rol6 {
padding-right: 10px;
}
You can also control which rules you don't want to flip by adding a /* @noflip */
CSS comment to your rule:
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
paddingLeft: '10px /* @noflip */',
},
});
/* Will be applied in LTR & RTL */
.f6x5cb6 {
padding-left: 10px;
}
Values than contain CSS variables might not be always converted, for example:
import { makeStyles } from '@griffel/react';
const useClasses = makeStyles({
root: {
// β οΈ "boxShadow" will not be flipped in this example
boxShadow: 'var(--box-shadow)',
},
});