Responsive Design
How to write mobile responsive designs in your CSS in Bamboo
Bamboo expresses responsive styles as conditional styles keyed by breakpoint.
Let's say you want to change the font weight of a text on large screens, you can do it like this:
<span
className={css({
fontWeight: 'medium',
lg: { fontWeight: 'bold' },
})}
>
Text
</span>
Bamboo uses a mobile-first breakpoint system, and writes responsive styles as lower-bounded range queries ā
@media (width >= 40rem). Ranges that also have an upper bound close it exclusively,
@media (width >= 40rem) and (width < 48rem), so a range stops exactly where the next one starts.
Range syntax needs Chrome 104+, Safari 16.4+ or Firefox 102+. The
lightningcss option lowers these queries against your browserslist targets,
which recovers most of that: a plain breakpoint becomes (min-width: ā¦) again, but an exclusive upper bound has no
older spelling and lowers to not (min-width: ā¦), so smDown, mdOnly and mdToXl still need roughly Chrome 88 /
Safari 14 / Firefox 64.
These queries carry no media type, so unlike the @media screen and ⦠Bamboo emitted previously, responsive styles
now also apply when printing ā against the page width. Wrap rules you want to keep off the printed page in an explicit
@media screen.
Bamboo provides five breakpoints by default:
const breakpoints = {
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1536px',
}
Overview
Property based modifier
Bamboo allows you apply the responsive condition directly to a style property, resulting in a more concise syntax:
<span
className={css({
- fontWeight: 'medium',
- lg: { fontWeight: 'bold' }
+ fontWeight: { base: 'medium', lg: 'bold' }
})}
>
Text
</span>
Why there is no array syntax
An earlier version also read an array as one value per breakpoint ā
fontWeight: ['medium', undefined, undefined, 'bold']. It has been removed, and an array in a style value is now an
error naming the property it was written on.
It was the worse of the two spellings on its own terms: positional, so it needed undefined padding to skip a
breakpoint, and it re-pointed every value if you inserted a breakpoint above them. But the reason it had to go is that
CSS already writes lists as arrays, so a font stack written the obvious way ā
css({ fontFamily: ['Inter', 'sans-serif'] })
ā quietly compiled to Inter at base and sans-serif at sm. No error, no warning, and nothing in the type to suggest
it. Write the condition object instead:
css({ fontWeight: { base: 'medium', lg: 'bold' } })
Targeting a breakpoint range
By default, styles assigned to a specific breakpoint will be effective at that breakpoint and will persist as applied styles at larger breakpoints.
If you wish to apply a utility exclusively when a particular range of breakpoints is active, Bamboo offers properties that restrict the style to that specific range. To construct the property, combine the minimum and maximum breakpoints using the "To" notation in camelCase format.
Let's say we want to apply styles between the md and xl breakpoints, we use the mdToXl property:
<span
className={css({
fontWeight: { mdToXl: 'bold' },
})}
>
Text
</span>
This text will only be bold in the md and lg breakpoints. The upper bound is exclusive: mdToXl stops where xl
starts, so it emits (width >= 48rem) and (width < 80rem).
Targeting a single breakpoint
To target a single breakpoint, you can easily achieve this by simply adding the suffix "Only" to the breakpoint name in camelCase format.
Let's say we want to apply styles only in the lg breakpoint, we use the lgOnly property:
<span
className={css({
fontWeight: { lgOnly: 'bold' },
})}
>
Text
</span>
Customizing Breakpoints
Define custom breakpoints by passing them as an object in your Bamboo config.
Note: Make sure that the CSS units of your breakpoints are consistent. Use either all pixels (px) or all em, but
do not mix them.
bamboo.config.ts
import { defineConfig } from '@bamboocss/dev'
export default defineConfig({
// ...
theme: {
extend: {
breakpoints: {
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1536px',
},
},
},
})Hiding elements by breakpoint
Set display under the range you want it hidden in ā md: { display: 'none' } from md up, mdDown below it. See
Display for the worked forms.