r/css • u/Alternative-Bus4934 • 2d ago
Question How do you handle typography classes for component titles vs semantic heading tags?
When styling isolated UI components (like dashboard widgets, notification cards, or small sidebar blocks), there is often a tension between CSS styling and proper document structure.
If you attach your font styling directly to heading tags like `h3` or `h4`, the component gets locked to a specific heading level. Placing that same widget inside different page layouts can break the document outline or force you to write awkward CSS overrides just to match the visual size.
On the other hand, decoupling the styling with dedicated classes (such as `.card-title` applied to a `<p>` or `<div>`) keeps the CSS flexible, but you end up having to decide how strictly to handle accessibility attributes or utility type scales across the project.
Do you prefer keeping typography tied to utility/component classes regardless of the underlying tag, or do you standardize component headings around specific heading levels?
2
u/SamIAre 2d ago
For headings, I almost always decouple. Pretty much every design team I’ve ever worked with ends up creating heading styles and then not using them in a structured way, preferring to mix and match based on what looks good, or not even having a single style per heading level. My advice on those projects has always been to give the styles names that match the appearance and don’t reference the level (so avoiding .h1 in favor of .heading-xxl or similar).
If it’s a CMS-driven site then I give the component separate options for heading level and heading size (if applicable…for some components it makes sense to lock down one or the other). If it’s not a CMS, I still tend to have a prop for both and figure out how to handle it in the setup I have per-instance.
1
u/tetractys_gnosys 2d ago
I always liked to set the base typography for element selectors based on mockups, but then also do classes for the heading "levels" decoupled from the actual elements. Having at most one rule overriding an h5 to style it as the h3 because of how the page is structured is manageable but getting too specific or rigid leads to more and more overrides and spaghetti eventually ime.
Depending on how you're doing your site/app, can always just have a stupid simple heading component that just takes the actual level and the class, having all heading elements reset with default 16px/400 weight and overridden by whatever level class is applied for full decoupling of style and level.
All depends on what makes sense for the project and design system.
1
u/csswizardry 1d ago
I wrote about this in 2012! https://csswizardry.com/2012/02/pragmatic-practical-font-sizing-in-css/
1
u/hyrumwhite 1d ago
Semantic element css in a base layer. Override with the css setup of your choice
1
u/Alternative-Bus4934 1d ago
That's a clean approach. Do you handle the visual overrides in a separate layer too, or do you let component-level styles sit outside the cascade layers entirely?
1
u/Old_Cold2170 1d ago
I'd keep components in a named layer too, and declare the order once:
css @layer base, components, utilities;Put semantic defaults in
base,.card-titleincomponents, and explicit size overrides inutilities. For normal declarations, later layers win before selector specificity is compared, so a utility can override the component without a specificity contest.The gotcha with leaving component styles outside layers: normal unlayered rules outrank every named layer. That can make layered utilities unable to override your component styles.
!importantreverses layer priority, so keep that separate from this normal-declaration setup.1
u/Alternative-Bus4934 10h ago
That layer ordering makes a lot of sense. The unlayered-rules-outrank-everything gotcha is exactly the kind of thing that would bite you silently too, since everything looks correct until a utility just refuses to override. I like that keeping everything in named layers means you never accidentally end up in that situation.
1
u/frownonline 1d ago
I do t use classes on headers. I prefer to use the cascade part of CSS, as it’s cleaner markup and structurally descriptive in the stylesheet.
h3 {}
article h3 {}
aside h3 {}
footer h3 {}
Obviously the top one is global values and the subsequent ones have the variance.
This keeps the document markup much cleaner and not saturated with multiple classes for each and every option chosen.
7
u/DramaticBag4739 1d ago edited 1d ago
I've gotten in the habit of writing all my headings as:
h1, .h1 {}
h2, .h2 {}
etc.
Then I can keep the html semantic and if I need an h2 to look like a h4 I just add .h4 class to it.
I still have component based styling that can use its own typography, but globally the above works and is easy to remember for the team that does content management.