12 ms·
Inline CSS works better in a component world
- gtsop 6y agoI 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.
- davnicwil 6y agoCould 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 :-)
- gtsop 6y agoYes 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.
- gtsop 6y agoSorry 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.
- weego 6y ago'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.
- zuhayeer 6y agoI'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.
- inglor 6y agoYou 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).
- ricree 6y agoDev tools allow live editing classes and other css affecting an element. What about this becomes easier when using inline css?
- FreeHugs 6y agoIn 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".
- inglor 6y agoNot 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.
- krageon 6y agoYou'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?
- ximm 6y ago> 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.
- somishere 6y agoInline means no logic /state / pseudo.
- davnicwil 6y agoWhat do you mean?
- wtf_srsly 6y agoThat 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.
- davnicwil 6y agoRight - 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.
- somishere 6y agoAh, 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?
- davnicwil 6y ago> 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!)
- floppiplopp 6y agoAnd 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.
- herrkanin 6y agoHuh? 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.
- pocket_titan 6y agoDid 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
- marijn 6y agoI'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.
- IfOnlyYouKnew 6y agoCascading / 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.
- 6y ago
- njsubedi 6y ago> Probably better compression by not repeating styles everywhere Repeating styles would be the least of the problem because of the gzip compression, no?
- onion2k 6y agoI 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.
- tbassetto 6y agoCorrect. I like the "Controlling File Size" of the Tailwind CSS project: https://tailwindcss.com/docs/controlling-file-size 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)!
- onion2k 6y agoBecause 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.
- mattacular 6y agoYou 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.
- j-krieger 6y agoYes. 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.
- davnicwil 6y agoThis 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.
- Ahch1eep 6y agoI'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/Using_shadow_DOM https://developer.mozilla.org/en-US/docs/Web/Web_Components/...
- chrismorgan 6y agoThis 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.)
- wtf_srsly 6y ago> 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.).
- ratww 6y ago> 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?
- diob 6y agoI 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.
- pvsukale3 6y agoTailwindCSS recommends a similar approach to avoid repetition of common css code. Abstract CSS components at framework partial/components level.
- habosa 6y agoYes! This is dead on. I can't stop evangelizing Tailwind lately: https://tailwindcss.com/ 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.
- romanovcode 6y agoYes, this is why you use tailwind.
- AndrewThrowaway 6y agoIt 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.
- ehnto 6y agoI'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.
- nicoburns 6y ago> 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.
- j-krieger 6y agoIf you use CSS Modules, you can not target an elements children with another css module class name. You can‘t know the hash beforehand
- nicoburns 6y agoYou 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.
- dsego 6y agoReusable 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.
- qubyte 6y agoI'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. https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
- RyanGoosling 6y agoI’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>
- qubyte 6y agoAttack 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.
- captainmuon 6y agoIn 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 <Dialog> <Button> </Dialog> 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 :-)).
- Izkata 6y ago> 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.