-
Notifications
You must be signed in to change notification settings - Fork 2
Styling
There are a bunch of libraries and techniques that we're testing out, Aphrodite, Glamor and styled-components are all in the mix. Making the move to purely JS controlled styles is a big step so we need to make sure it's not too jarring, some libraries look properly crazy so the closer we can keep our component styles to actual CSS, the better.
- Server-rendering
- Support for all CSS
- Performant and small file size
???
export const listitem = css({
backgroundColor: grey.light,
display: 'inline-block',
paddingBottom: '4px',
verticalAlign: 'top',
'@supports (display: flex)': {
display: 'flex'
}
},
media(`(min-width: ${breakpoint.small}) and (max-width: 899px), (min-width: ${breakpoint.large})`, {
width: '50%'
}),
media(`(min-width: ${breakpoint.small}) and (max-width: 899px), (min-width: ${breakpoint.large})`, nthChild('2n + 1', {
paddingRight: '4px'
}))
)
orrr
export const listItem = css`
background-color: ${grey.light};
display: inline-block;
paddingBottom: 4px;
verticalAlign: top;
@supports (display: flex) {
display: flex;
}
@media (min-width: ${breakpoint.small}) and (max-width: 899px), (min-width: ${breakpoint.large}) {
width: 50%;
& nth-child(2n + 1) {
padding-right: 4px;
}
}
`
maybeee
const specialBreakpoint = `(min-width: ${breakpoint.small}) and (max-width: 899px), (min-width: ${breakpoint.large})`
const styles = css({
backgroundColor: grey.light,
display: 'inline-block',
paddingBottom: '4px',
verticalAlign: 'top',
'@supports (display: flex)': {
display: 'flex'
}
},
media(specialBreakpoint, {
width: '50%'
}),
media(specialBreakpoint, nthChild('2n + 1', {
paddingRight: '4px'
}))
)
I still have reservations with the object syntax, during the test build of Shortlist Studio I stalled a number of times as I struggled to implement a simple CSS feature. The mixture of integers, strings, template literals and variable references is a bit nasty. Handling media
, nth-child
, supports
and other CSS stuff is inconsistent. These sort of issues create a fairly steep learning curve for anyone who hasn't worked with the code-base or a similar library.
I really like the tagged template literal syntax, we can write actual CSS. All @media
, @supports
, nth-child
, ::before
s and the like can be written consistently. It still allows us to call variables/tokens from the design system in an ${expression}
.
Alright, so, tokens. I think these can be awesome. They're essentially variables for design information but generic enough that they can be utilised outside of the website, think React Native, iOS/Android apps, styleguides. They should be defined as JSON or YAML or some configy data type. The idea is best sold by one Daniel Eden:
Systems like Tachyons et al. approach this problem by instead documenting and limiting properties of components. (I like to think of this as “subatomic” design.) You then create components by composing subatomic components (properties). Rather than creating a component and its variants, you simply have a comprehensive list of “ingredient” subatomic components. Those subatomic components can be combined in thousands of ways to create hundreds of components. The properties of those components are numerous, but constrained to a set of acceptable values (our subatomic components).
So in our system these tokens represent the multitude of properties that can be utilised by a component, they can be as simple as a series of colours or font families but can also represent a scale of spacing, animation properties, vertical layers, aspect-ratios and the like. Instead of using them as classes with predefined CSS properties (padding-top
, background-color
), we'd keep the values separate to allow flexibility in how we want to use them. They could be used in an object like so:
const style = css({
color: theme.primary,
fontFamily: family.display,
fontSize: fontSize.large,
letterSpacing: tracking.wide,
marginBottom: spacing.medium
})
But can also be mixed with non-token values, preventing us from getting locked into a system when realistically we'll need to tweak these values during build.
const style = css({
top: '2px',
left: '2px',
backgroundColor: theme.primary,
position: 'absolute',
width: '150px'
})
Tokens could be imported into this system using simple objects, destructuring could be useful in this instance as well. import { color, shadow } from './tokens'
export const color = {
primary: '#ff0',
secondary: '#f00'
}
export const shadow = {
low: `0 0 2px 2px rgba(${grey.primary}, 0.25)`,
high: `0 0 20px 10px rgba(${grey.primary}, 0.5)`
}
export const space = {
xsmall: '4px',
small: '8px',
medium: '16px',
large: '32px'
}
- theme colors
- neutral colors
- font-families
- font-sizes - (scale)
- font-weights - (possibly, might not be relevant)
- line-height - (scale)
- letter-spacing - (scale)
- layers - z-index (scale)
- spacing - padding/margin, space between elements (scale)
- sizes - sizes of elements (scale)
- border-weight - (scale)
- box-shadows - (scale)
- animation duration - (scale)
- animation easing - (scale)
- aspect-ratios
- border-radius - (scale)
- icons