Hacker News new | past | comments | ask | show | jobs | submit login
Inline CSS works better in a component world (davnicwil.com)
54 points by davnicwil on Aug 20, 2020 | hide | past | favorite | 88 comments

This article seems to completely ignore the biggest area where inline CSS is problematic: dynamic, state-dependent styles. That is, things like pseudoclasses (hover states and the likes) and media queries.

You can do these things in JavaScript: match your media queries in JavaScript and change the inline styles, and reimplement :hover, :focus and the likes. But I expect (without supporting measurements) that doing this for everything will be fairly bad for performance, and it will generally be less responsive (in the performance sense of the word rather than the resolution-independence sense of the word), e.g. your state-dependent styles may apply a frame later than they should. And I don’t like to depend on JavaScript without good cause.

This is where utility CSS frameworks strike the balance: by using regular class names for the effects of inline CSS, they can apply media queries and psuedoclasses. It’s an interesting approach that I haven’t used yet but I’ve steadily been coming around to the notion of for some sorts of projects.

(There are also pseudoelements; those can’t be implemented with inline CSS at all.)

I went from styled, to just using style as much as possible, to finally using tailwind. It's a wonderful development experience, and I hardly ever need to go beyond it. Can't recommend it enough, it makes developing quicker and simpler. And in the end, the product ends up looking way more consistent than anything else I've tried.

I wish there was a mode to tree shake tailwind in production. Automatically extract all the class arguments into css classes for a cleaner markup

While there is no automatic way of doing it (as far as I know), I have been using Tailwind's @apply directive for things that are used site wide and that has worked out well. Really excited to use the latest 1.7 version that makes this process even easier given you don't need to split up pseudo classes https://github.com/tailwindlabs/tailwindcss/pull/2159.

> You can do these things in JavaScript: match your media queries in JavaScript and change the inline styles, and reimplement :hover, :focus and the likes. But I expect (without supporting measurements) that doing this for everything will be fairly bad for performance, and it will generally be less responsive (in the performance sense of the word rather than the resolution-independence sense of the word), e.g. your state-dependent styles may apply a frame later than they should.

It's also fairly bad practice to put your CSS into JavaScript for a number of reasons (such as accessibility, disabled javascript etc.).

> It's also fairly bad practice to put your CSS into JavaScript for a number of reasons (such as accessibility

Could you explain why it would affect accessibility?

In the old model, you had semantic markup (ideally) and css on top, that you could swap.

He says: " in modern web apps we don’t only render content in simple single-element containers like boxes and circles, but in drawers, modals, floating panels and other complex, multi-element components. [...] All web frameworks have a good abstraction for this, of course: components. [...]"

Now, I've always missed a way to apply style on top of complex components. You can still use CSS, but as he says there is a mismatch when you change the internal HTML structure. It would be great if you could use React components like

and then specify separately in a theme component the styling - not just CSS, but also what elements to use to build it up. Of course, you can just use separate components for each theme - ModernButton, DarkButton, RetroButton. But there is a lot of room for errors and the interfaces can diverge. Better to have one opaque Button component that gets passed the Style from somewhere else.

I actually started working on something like this - a Electron based Desktop Widgets tool, where you could write components in React and switch themes. But since I'm a React novice I could not find an architecture that I was happy with (and the idea of using an Electron instance to decorate my desktop to monitor performance seemed a bit crazy :-)).

> ModernButton, DarkButton, RetroButton. But there is a lot of room for errors and the interfaces can diverge.

Our solution for this was to have an internal Button in the library that defines the interface and handles the functionality, then ModernButton/DarkButton/etc simply use Button in particular ways, blindly passing along everything else they were given.

And so, the modern web becomes an unmaintainable, monolithic clusterfuck with the illusion of modularity. It's the idea of the 90s with the complexity of 2020 - just because people cannot handle the simple core concepts of CSS.

I'm not going to defend the article, but I really bristle at this idea that if you just _get_ CSS it isn't problematic anymore. CSS tries to solve a hard problem and it's certainly preferably to inline-everything, but its design (global, cascading, with many types of behavior—positioning, z-stacking, etc—depending on the styling of parent elements in interesting ways) is actively hostile to many kinds of modularity, and that's a real issue even for people who "get" CSS.

Cascading / depending on the parent's style are features specifically intended to enable a component-based approach. It allows, for example, to use h1's in your component, but have them render at appropriate sizes depending on their level in the overall hierarchy.

Cascading is, to me, like class inheritance in object-oriented style of programming. Useful in some cases, but can become unmanageable with more than a few layers.

The "inline CSS" approach is an escape hatch to avoid cascading styles. I can see its advantages, to apply all (and only) the styles on the component level.

Apparently someone didn't appreciate the jab at OOP. Well, I call it like I see it - seen more messes made by class inheritance and cascading, than without.

There's also this grouping method to separate classes https://piccalil.li/cube-css/ it's cringe at first but so was BEM and it's still useful even if you combine both

Huh? This is a direct response for the fact that any sufficiently large vanilla CSS has a high risk to turn into an unmaintainable, monolithic clusterfuck.

Did you even read the article? People can handle the "simple core concepts of CSS" just fine - you're interjecting your own pessimistic opinion here & passing it off as fact. No, the article states how the abstraction of CSS classNames doesn't fit well with the idea of using modular Components. You're still writing CSS, heck, styled-components even _adds_ features on top of it. But sure, just keep echoing this "web dev stupid" mentality

Yes! This is dead on. I can't stop evangelizing Tailwind lately: https://tailwindcss.com/

If you're using any component-based framework (I use Vue) it's an incredible experience. The stylesheet they provide helps you be consistent and inline styles help you move quickly. The natural ability of components to scope their markup and styles means that your code is actually DRY.

The barrier to make changes is so small. You don't have to refactor CSS classes as your HTML hierarchy changes, you just make the style changes in place.

It's such a powerful paradigm that it has made my designs much better. I get consistency for free and I can quickly translate from mental image to reality.

It may look ugly but don't knock it til you've tried it. It changes everything.

I'm still against inline CSS and what are essentially inline css helper libraries (tailwind etc), but a big part of maintainability is co-location of related code, which inline CSS provides at the cost of readability and control. I feel you can get most of that benefit with well organised SCSS, specifically something similar to the components/contexts model.

For components, you have no styles outside of your component partials, so nothing influences a component except what's targeting it. All targeting is via BEM naming, so no inheritance even for nested components.

So that's components, however sometimes things change depending on their context, which is really messy if you're using inline styles. You end up introducing logic, or you end up with different kinds of components for different contexts and having to maintain them all.

When using components/contexts, if for example a product-card on the checkout needs to look different in some small way. You just have a _checkout.scss file, and in it you target .checkout-page .product-card, and that's it. Simple, clean, no weird inheritance/overriding issues, just hygienic scoping of CSS and one level of inheritance available if needed.

The product-card never has to concern itself with checkouts, and the checkout knows it has a product card so it makes sense that it controls any changes it wants.

I've been using this method for a while now, the majority of the time you end up with ~10-20 small component files, and then 4 or 5 context files with maybe 20 lines in them. You know exactly where all styles affecting your component live, it ends up really clean and easy to maintain.

> All targeting is via BEM, so no inheritance even for nested components.

If you use (S)CSS modules, then you don't even need to worry about BEM.

Seconded, when you have a large codebase, BEM selectors end up taking a considerable amount of kB on your final bundles. Moving to CSS modules and running a css class minifier and deduplicator is the best thing you can do if you work in a project where performance is critical.

Anecdotical, but the best improvement I've achieved doing this is shaving off ~30% of our final bundles, gzipped!)

If you use CSS Modules, you can not target an elements children with another css module class name. You can‘t know the hash beforehand

You could import the parent CSS module in the child. It might not be a bad idea to make the dependency explicit like that if the components are so tightly coupled.

I'm mostly a server dev, and I'm keen on a nice strict Content-Security-Policy (CSP) header which rules out inline CSS. The benefits (preventing extensions etc. from injecting style in a way which may constitute an attack) outweigh the convenience of inlined CSS for components in my opinion.


I’m curious. Can you provide an example where CSS can constitute an attack?

How does your CSP stop a script from adding styles to DOM elements? <script> document.querySelector(‘body’) .setAttribute(‘style’, ‘my malicious css?’); </script>

Attack is stretching the term sightly, I admit. It’s possible for a malicious style to reorganise things on a page in a misleading way, or place a lewd image in a background for example.

Edit: As for scripts adding things, the CSP prevents the style attribute being applied iirc.

I've been rewriting my personal/private tools from React to standard webcomponents, lately, and one of the things I love the most is the shadow dom [1], which allows to sandbox styles within a component. It's best of both world, basically.

[1] https://developer.mozilla.org/en-US/docs/Web/Web_Components/...

    In modern web applications, it's
    pretty self evident that components
    are the right solution
I often see this argument of "self evidence" made by developers who claim that some modern "best practice" approach is the right one.

In my experience it is an indication that the proclaimed "better" approach is actually inferior. And the author had to resort to the argument of "obvious self evidence" because there are no better arguments around.

I think it is driven by what I call "tool religion". Developers who invested significant amount of time into learning a tool become religiously attached to it. Because they now want to be an "expert" of the "best way". Not just "Some guy with a preference".

Every CSS rule is effectively in global scope. And as the complexity of web apps increases regression testing becomes a bigger and bigger challenge. Being able to insert components multiple times and not having to worry whether an innocuous CSS change can result in "spooky action at a distance" really helps.

I think this is a reversal of the best practice of complex CSS class hierarchies. Having flatter and fewer CSS classes and more inline CSS will result in redundant style information, but having fewer CSS rules apply to nodes is a win overall.

Every CSS rule is effectively in global scope.

They are, and that's why sibling and child selectors exist. If you only ever define simple classes with no thought about how they'll work in the overall app then you're in for a bad experience with styles cascading to things they're not meant to affect. If you actually use CSS the way it was designed then you have complete control over exactly what styles are applied to which elements.

A good rule in component based development is to define a class name for the component and use ".unique-component-class-name > .class-for-things-in-this-component" to limit the application of styles to that component. This takes a bit of discipline but it's pretty obvious when you get it wrong.

Yes indeed. Say you're creating a new component, and this new component will contain (among other things) some existing component, but the existing component needs to be styled slightly differently in this particular context. How do you deal with this with inline styling? Threading around this information between the components in JS to make the old component aware of the new one seems clearly wrong. A good old-fashioned style sheet handles it easily and relatively cleanly.

I've seen that inline CSS seems to be the latest trend, but I haven't really read up on why myself. Is this post really the current thinking? I find it completely uncompelling.

The rule we've come up with is essentially "don't do that". But if you need to, instead of having styles cross boundaries, the inner component should be configurable (either by making two versions of it, or having something like "mode=large" as an abstraction over the CSS it needs to apply to itself).

the existing component needs to be styled slightly differently in this particular context.

See my other comment in this thread (https://news.ycombinator.com/item?id=24221241) for how I'm tackling that sort of problem at the moment. tl;dr Work out what the dev should be able to override in the style at runtime and make it a CSS var that's set inline in the component. As I said there, it might not be the best approach especially in very large apps, but it does seem to be working well for me.

    Every CSS rule is effectively in global scope.
We had this problem in programming forever. These days, you can put your function in a class in a namespace ... still the namespace sits in global scope. But we never came to the conclusion that we should make all code inline to solve it. Fortunately.

So if you make a CSS rule to make links in your userlist red:

    .gizmosUserlist .name a { color: red }
Then yes, it will apply to other .gizmosUserlist instances.

Shadow DOM is a way to prevent it if you want.

Personally, I think it is a good thing, that you can make all links in all gizmosUserlists red if you like and can target a specific one with a more specific selector if you like.

the inline CSS is not redundant, because redundancy only applies to the source, not the output. And in a component world, the source is the js/compiler/component source code, and the output is what's on the page. I wouldn't care if the css is repeated for every component that's rendered, as long as it's clear from the source code of the component (or js source).

Nobody bats an eye when a compiler unrolls a loop, and you get N copies of the same code in assembly. In the same sense, nobody should care how clean the "assembly" of the web is (CSS+HTML).

I'll believe that CSS+HTML is the "assembly of the web" once I have to touch them as little as I have to touch the output of my C++ compiler or Java bytecode. Right now, any web developer has to be very comfortable with debugging HTML and CSS issues, whereas it's entirely possible for a competent Java developer to know literally zero about bytecode.

That argument falls because it was never designed that way. If you want broad browser support and careful testing of edge cases you can't threat it that way, even with WASM you likely won't escape it.

a proper C++ or java dev will examine the byte code if stuff is broken (if required), just the same as they would when writing react apps. You wouldn't normally need to examine the output the html or css when you use a framework as high level as react (or really, most web component frameworks).

At some point people should care because most applications delivered over the web perform by the rules of entertainment meaning that if it takes too long to load or render people leave and look for their entertainment elsewhere.

You have to really try for that to happen.

There's another very good reason to make a claim of "self evidence" besides not having any good arguments, which is if the proposition actually is self-evident to the target audience, and you want to focus on something else rather than dive into a long justification for the proposition.

I think the author is justified in saying that designing with components in web development has become self-evidently better than not. All new web frameworks are component-based. Web Components were added to HTML. Pretty much all web developers agree on this.

Are you a web developer? Do you disagree that the benefits of components in web programming are self-evident? If so, that is definitely surprising to me, and probably to the author.

I think we should spend a minute on what is meant with "components" in the article.

Would you say that this very site - Hacker News - is using this type of "components"?

The latest possible start date for components on the web was when PHP/fi (or whatever it was called) allowed you to ```include``` other files.

Realistically, people were probably doing the same with perl scripts before that.

And any definition of component is going to find it hard to exclude standard html elements, other than by specifying that it's users being able to define new ones, and not just browser vendors.

Incidentally, CSS was the original implementations of user-defined components: it allows defining certain behaviours once, for a "class" or group of similar elements, then using it repeatedly.

I don't think that is the type of "component" the author means when he writes about a "component world". He constantly talks about his argument applies to "modern web apps".

I don't have the feeling that what he really means with "Inline CSS works better in a component world" is "Inline CSS is the better choice since the 90s".

I remember when we loaded xml into a buffer in c and replaced template tags with search and replace.

Yes! A comment box is a component. The tree view you look at comments in are components. Usernames and scores are component. A shared „link“ on the frontpage is a component. HN is not rendered on the client side, but its backend uses these „components“ via a templating framework. Components are just templates for the frontend.

This definitely leads me to believe that you don't have much experience with modern web frameworks. The meaning of "component" in modern web development is pretty consistent. You can think of a component as a custom HTML element (though they can be much more complex than built-in HTML elements). In fact, if you are using HTML Web Components, then your component literally is a custom HTML element. But the metaphor works even when generating HTML server-side: If you can reference a piece of UI by name, and pass it attributes, and it packages up some HTML/CSS/JavaScript in a reusable fashion, then it's a component.

Your question is slightly nonsensical, because components are not a design language, and it's not something you can see by looking at a rendered web page. To know whether Hacker News is using components, I would need to look at the source code, because components are a programming paradigm.

If you're asking me to comb through HN's JavaScript to see if they use that paradigm, well, no thank you.

    This definitely leads me to believe that
    you don't have much experience with modern
    web frameworks
Here we go again. It would have suited the discussion even better if you said "it is definitely self evident".

But I explained why it led me to believe that. You're just...not gonna respond to any of my argument...are you?


This is only discussing about whether the premise that components is the right abstraction is self-evident.

That's all, nobody else in this particular thread said anything about whether that means inline styles is the way to go.

You might want to post your question to the author of the blog post, or as a top-level question.

Not going into the CSS vs. inline bit (I think CSS modules solved this for components years ago) but I think composing components is a reasonable abstraction and it _is_ self evident because it's what we've been doing everywhere else.

"Component based" is basically just "functions composing other functions and calling each other in a top-down flow with bottom-up updates through framework state". It's "evident" that it's the correct abstraction because the alternatives (things like managing app state and UI interactions through MVC, MVVM and MVP) are mostly not needed or are not the right level of abstraction for composing large UIs in web apps (where components make it trivial and shift the complexity to stitching the state manangement <-> component interop when you need to break the abstraction).

Also - components are pretty uncontested these last few years.

You've outlined a preference, but you haven't informed the reader why your preferred solution is superior other than by saying that it makes your problems "trivial" (which in any moderately complex problem space is extremely unlikely).

If I can't see it given that I have actual experience with what you're talking about and can reasonably be expected to have the background to understand, how is someone from a different field supposed to understand what you wrote?

> components are pretty uncontested these last few years

I don't think so. Many people still use traditional frontends, i.e. static or server-rendered HTML and CSS.

Components are newer and there is still more to talk about, so they naturally are more prominent on sites like hacker news. That doesn't mean they are uncontested in practice.

SSGs use templates with template arguments. How is that different from a component?

This is a good call - 'self evident' isn't the best wording. This was just meant as a statement that the component model is dominant in modern web development.

The rest though is not what I intended to get across. I've done it both ways, the inline way works better for the component model is what I'm saying. If a different model comes along in future, there may be a better approach and I may switch to that.

This isn't about there being one right way, just more appropriate ways for different paradigms.

Because why would you care about caching static assets like CSS files in the browser, right? Loading all that data every time the page loads makes a developer's life easier and we don't care about users and their bandwidth obviously. Hmm. Perhaps if you're David Nicholas Williams, but not if you're me. I only want users to have to download things they need once.

I've been experimenting with a sort of hybrid model of dynamic CSS recently levaraging CSS variables. Most of the styling work is done in static CSS files for things that won't change (because caching is good), and those styles are applied to components with classes. The dynamic bits are also defined in CSS, but populated with CSS variables that have values set inline in the components. A trivial example would be;

    .panel {
      flex: 1;
      background-color: var(--themeBackgroundColor);

    <Panel className="panel" style={{'--themeBackgroundColor': `${userDefinedColor}`}} />
I don't really know if this approach is better than either plain CSS or styled components yet but it has solved some relatively complicated issues I was having with calculating positions of things and needing waaaaaay too many classes.

This is a good point - At the end I mention some built in advantages of global, externally defined CSS and I should add the point about caching to that list. I also mention more powerful implementations of inline styles, though, like styled-components, which you can actually use to generate cachable stylesheets on the server while keeping all your CSS scoped inline.

One thing I'll go back and reword in the article is this notion that inline == style attribute. I can see how this comes across, but I'm really talking about 'inline' the pattern more than a specific implementation. Using CSS-in-JS to add styles to a style attribute is one implementation, with, as you point out, some downsides - there are others that provide more features while keeping the component-centric model.

You can use tools such as webpack to write css scoped to component-level so that it extracts and bundles all that css into files so the user can still benefit from browser cache between deployments. This is of course a great deal of tool/config complexity but it may be worth it depending on your app.

Yes. This has been a default since Webpack 3. The fact that most people on this site don‘t know that all modern bundlers extract css shows they have no clue what they are talking about.

This is a pretty sweet design. This is why I come to HN! Amongst all the noise, you have pearls like these.

TailwindCSS recommends a similar approach to avoid repetition of common css code. Abstract CSS components at framework partial/components level.

I've been on the inline CSS hype, it makes rapid prototyping so much faster. Also if you use Dev Tools / Inspect Element to dynamically edit your web frontend its so much easier to test things and then just copy it over.

You don't need to copy it over - that's an incredibly frustrating flow compared to what you can get where you have to copy the correct thing or a refresh overrides your work.

- If you use something like React, Angular or Vue - use the CLI a loader with "hot reload" so changes in your files are instant and don't interrupt app state. That's the "best" option. - If you're stuck on an old build - set up storybook or just a separate endpoint where hot-reload works/is possible. - Otherwise use the Chrome DevTools "workspaces" feature that lets the Chrome devtools write automatically and update your files - that would save the "copying it over" part and also supports things you'd expect (like source maps).

Dev tools allow live editing classes and other css affecting an element. What about this becomes easier when using inline css?

'probably better compression' is an understatement.

As ever the answer is no one way is so superior in every circumstance that the other should be dismissed outright.

Defining your overall base and then only specifying the 'diff' between the base and the component is probably a reasonable goal.

Having said that, I don't like and don't do inline CSS.

Reusable components != reusable styles. Many functionally or semantically different components can resemble and share the same styles. One solution I guess with inline is to have a few levels of nested containers and params? Like <RoomyBox withShadow roundedBorder><LayoutBox><>etc etc</><LayoutBox></RoomyBox> vs <div class="layout roomy-box">. Not sure if this is much better way of reusing common styles than using css classes.

It would be interesting to see some data, some A/B test of these ideas.

Let's take some projects of various complexity - some personal webpage, online calendar, social app, etc.

And lets do these in Vanilla CSS - just some clean proper style.css in the <HEAD> and exactly the same project with all the inline styles with some JSS etc.

And let's discuss then. At what point in project's complexity what makes more sense. Which code is more readable/maintainable/etc. Performance gains and etc.

I feel like this is yet another© solution to an arrificial problem caused by inability to understand the web platform and existing tooling options. I can't even list the multiple levels of wrong with this approach.

Could you list a couple of the most important ones? If aspects of my approach are wrong or could be improved, I'd be really interested in learning why :-)

Yes of course:

- Sharing styling libraries (currently done via css files) across multiple web development teams, giving the ability to a central team of designers/developers to modify the look and feel of dozens of websites of the company

- Media queries, sass mixins and functions

- Components can be used in different contexts. The styling can be dramatically different in these contexts. Overriding the "style" attribute is harder than overriding a css class definition.

- Worse developer experience while trying to reason about the styling of a particular page. Image you have a page composed of multiple components. I think (and thus argue) it is easier to glance at a css file (or multiple css files) to understand how the whole thing fits together, instead of looking at all the individual components files, mentaly filter out the markup to keep the css and try to compose a wholistic picture.

Sorry I think my initial comment comes out as a bit irrespectful to you. Made it on my mobile and didn't have the patience to fully elaborate, I should have updated it, can't now.

> Probably better compression by not repeating styles everywhere

Repeating styles would be the least of the problem because of the gzip compression, no?

I suspect that if you're using React's 'style' expansion using an object, the order of styles that are written inline is going to be non-deterministic which means your compression won't be optimal. It'll still work, obviously, but not as well as the compression you'd get if you used a class name.


I like the "Controlling File Size" of the Tailwind CSS project: https://tailwindcss.com/docs/controlling-file-size

They DO tell developers to remove unused CSS when building for production of course, but in case you ship the whole (big) default file, it goes from 2309.7K to 180.6K (Gzip) or even 43.6K (Brotli)!

Inline means no logic /state / pseudo.

That used to be the case, but it’s not true any more. You can use custom properties to react to media queries and pseudo selectors. See https://propjockey.github.io/css-media-vars/

That's just a hack using css custom properties that still requires a global css file to define all breakpoints on the html element.

Also, how does it work for pseudo elements, state selectors etc. ? I can just see examples for media queries.

In my opinion it's also not really nice to read, just look at the example on his github page https://github.com/propjockey/css-media-vars.

Do you really think this is easier to read than normal media queries ?

Yes, you still need a CSS file or <style> tag to set up the breakpoints, but it’s going to be tiny and not something you actively work in unless you want to add a whole new breakpoint.

I also agree that it’s not particularly easy to read, but since the whole premise is that you are writing components, you can simply abstract away this ugliness in whatever way makes sense to you.

The result is similar to various CSS-in-JS solutions, but conceptually simpler: instead of having a library that has to manage inserted stylesheets and generated class names, you just generate (uglier) inline CSS directly. It also makes static HTML output trivial, without any of the fragile build process used for CSS-in-JS - all you need is that one static CSS file and the generated inline style attributes.

Hadn't heard of using custom properties like this. That said it feels like classes would provide a better, more extensible solution

What do you mean?

That you can't have inline pseudo elements, state selectors etc. There's a lot of stuff thats just possible with a proper css file / tags.

Right - I mention this at the end of the article. By inline I'm not talking only about literally the style attribute but the inline, component-scoped pattern. For instance things like styled-components allow the full feature power of CSS classes, just inline rather than in the 'global' style.

Ah, so you mean a scoped stylesheet included in the same file as the rest of your component markup. Agreed this is a useful pattern in the right circumstances! Depending on your build process (and how you're using components), in the old days this method just saw a global stylesheet deployed as usual, except with automated / custom scoping applied via data attributes. Do web components use shadow-dom style scoping now?

> so you mean a scoped stylesheet included in the same file

Exactly - perhaps 'colocated styles' might be a better term than 'inline styles'.

> Do web components use shadow-dom style scoping now

Not sure, I don't use or know much about Web Components (the technology) - by 'component' I just mean the web framework pattern of modularising a bunch of markup/behaviour (and styles if you agree with the arguments in the article!)

Yes, as mentioned in another comment I meant you can't do anything beyond styling the element in its current state. Consider a wild state-based rule along the lines of: `input:checked ~ output[data-i="0"] + section > div:empty ~ div:last-of-type:focus-within::before` .. for that you would need a stylesheet.

Yes, this is why you use tailwind.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact