Use data attributes for css
This is a suggestion, and needs to be investigated
Today we have explicit classes for sizes, etc. - but it would be nice if we can have a good developer API for this, even if our users use just CSS classes.
A proposal is to use data attributes like we use props in react, so things like size and variant are the same across all components.
This is also how we will do theming, so it plays nicely with that,
Given a button we want to be small. secondary variant and danger color, we would do this:
<button class="fds-btn" data-size="sm" data-variant="secondary" data-color="danger">
button
</button>
Our css would look like this:
.fds-btn { ... }
.fds-btn[data-size="sm"] { ... }
.fds-btn[data-variant="secondary"] { ... }
.fds-btn[data-color="danger"] { ... }
A big plus for doing this is that our users only need to set one class to define the component. It is easy to select, and change a data attribute with javascript, easier than classes:
let value = el.getAttribute("data-size");
el.setAttribute("data-state", "sm");
CSS Trick has a great article about this
This might be related to #1952
Do we have an example of other css frameworks that have done this approach?
Do we have an example of other css frameworks that have done this approach?
I don't know of any framework that does this currently, I did a quick look and did not find any. Another small plus I thought of, is also the lowered risk of adding multiple classes of the same type, ex.: two variant classes
If the project wants to eventually move to web components I think this could be done. The attributes would not have to be data attributes, they could simply be any self defined ones in a web component.
I guess most systems like to separate code and styling. Dom attributes deal with everything except styling while the classes are used for styling.
Most web component + design systems don't use this after some searching. But I found some that do:
- Redhat https://github.com/RedHat-UX/red-hat-design-system 🌞 Example here: https://ux.redhat.com/elements/button/
- Nordhealth https://nordhealth.design/components/button/
- Pharos https://github.com/ithaka/pharos https://pharos.jstor.org/storybooks/wc/?path=/docs/components-button--docs
They all attach it to the root of the web component with a attribute selector :host([variant="secondary"]) button type selectors
Microsoft fluentUI also does this: https://github.com/microsoft/fluentui/blob/master/packages/web-components/src/button/button.styles.ts#L311C5-L311C46 But they have a different solution to generate a stylesheet for each component 🤯
It seems like React Aria quite a bit
ref
I like this approach, and its also possible to do [data-placement*="top"] to check if data-placement="top left" contains top. JS-wize we can use the el.dataset.placement API as well.
Another advantage data-attributes gives us, is a quite similar React and HTML API:
React: <Button variant="primary">
HTML: <button class="ds-button" data-variant="primary">
It also prevents the consumer from adding a invalid combination of classes:
Wrong: <button class="ds-button ds-button--primary ds-button--seconrdary">
Can not go wrong: <button class="ds-button" data-variant="primary">
Considering every class name should be prefixed by component name (i.e. ds-button), rendering data- does not make that big of difference in terms of kilobytes :)
We agreed to pursue this way of defining component variants and styling using data attrs in CSS.
Performance is negible in 2024 with classes vs data attr selectors.
Additional information: we'll use the data-ds- prefix to minimize risk of namespace conflicts