21 ms·
My favourite 3 lines of CSS
- microflash 4y agoVery nice. I like the elegance of owl selectors, particularly when describing the spacing relationships between adjacent siblings. It helps avoid bleeding issues of space which used to require :last-child / :first-child / :only-child overrides.
- shashanoid 4y agoMine's display: flex, flex-direction: row, justify-content: space-between
- sjsanc 4y agoAbsolutely. You can usually drop the direction though as it's the initial value. But flex is so powerful for layouts, I'll slap it on almost anything, and barely have a need for grid.
- Gare 4y agoYou can now even use `gap` on flexbox.
- changethe 4y agoagreed. grid & flex, combined with a standard set of custom spacing/gap utils for your design system are making life so easy when trying to build coherent layouts.
- floodle 4y agoThis immediately made me think of Dave Matthews Band...
- ibejoeb 4y agoI was hoping this was addressed in the article, and it was, under "Why use margin and not gap?" A number of arguments are presented (including that, at the time, it wasn't an option) and the confluence of those make the owl compelling. I think I'd probably opt to buy into flexbox/grids and gap for greenfields projects, but I do appreciate the notion of flow axioms and styling the space between adjacent items.
- ironmagma 4y agoIt’s amazing that CSS has such advanced features that can do these things, but at the same time if you actually use them extensively and then I inherit your code, you kind of deserve a knifing.
- tangue 4y agoWorst thing is the comment (if there's any) is probably something like /* lobotomized owl typography*/
- ImaCake 4y agoWell at least you can google it… But it certainly doesn’t help. I keep my css specific to each class and try to be as explicit as possible to avoid any weird consequences.
- the_other 4y agoFor me, your approach makes the CSS harder to maintain. Pages have loads of repetition and patterns. I’d hope to find a good balance between DRYing up patterns that benefit from it, and leaving space for special cases. I find code patterns like the owl/.flow shown in the OP help greatly with that. Your approach, redefining all the properties per class, echoes avoiding using parent+subclass relationships in OO style code. Sometimes you benefit from the generalisation of a class hierarchy, sometimes you don’t. A hard rule in either direction gets in everyone's way.
- ironmagma 4y agoThe 'C' in CSS was a mistake. Consider that specificity is even a thing, and then consider that the ordering of your declarative CSS code matters. IDK, it does seem necessary to make the language workable, but there are far too many stylesheets out there with specificity hacks and !important.
- the_other 4y ago
- woahitsraj 4y agoWe get so much power from just setting global scoped styles like this it's so strange to me that more of these patterns aren't common or included in minimal css frameworks. With all the recent criticism of tailwind, css-in-js, and other bloated frameworks I truly feel like 90% of projects could get away with a handful of sensible global styles or "classless css" and then aggressive use of components with scoped styles. You hardly ever need anything else
- splitbrain 4y agoThis. So much this. I wish I could make my colleagues understand.
- xialvjun 4y agoThat requires the program itself to be well designed, without exceptions everywhere.
- woahitsraj 4y agoI think exceptions are fine and that is what you could use inline or scopes styles for. Exceptions everywhere is problematic but having this sort of pattern could encourage better design
- grishka 4y agoHere are my favorite 4 lines of CSS: *, *::before, *::after{ box-sizing: border-box; overflow-wrap: break-word; }
- anon___ 4y agoThis reads like a haiku.
- the_other 4y agoPersonally, I dislike it. Firstly, it’s too general. Most boxes don’t care which sizing model is being applied. I have found that I want explicit control more often. To be fair, I learned web development when I had no choice but to work with both models so I don’t find the switching much of a burden. Second, I’ve seen * { box-sizing: border-box; } cause whole areas of the screen to disappear due to a bug in Chrome. This was years ago, so those bugs have probably been fixed, but it was such a significant problem to the layout and caused by such a generally applied rule, that it’s put me off.
- jraph 4y agoThere have been countless times when I was fighting with some margin / size issues, only to notice a * { box-sizing: border-box; } was breaking my expectations. I learned CSS with the W3C / standard box model, in a time where we had to deal with the buggy IE behavior which was essentially box-sizing: border-box. Now, we have the choice of specifying which box model to use and is seems many people prefer box-sizing: border-box. I'm definitely used to the standard/default one more but odds are someone overridden this. I don't know which one is better but now we have two existing box models, and depending on the project you work on, the default one depends on what was decided when starting it. It's weird, before it was depending on the browser in use, not the project :-) I'm not sure how this interacts with libraries / components you import that might not expect such a global setting. I guess you have to be very defensive about this when writing a component. And it seems the expectation is that the component writer should be defensive rather than the website / app builder be careful not to break stuff with global rules. Which is also weird to me. The spirit of the cascading styles was that you could style and customize everything and that stuff you import would adapt to your styling, but we are rejecting this idea by going out of our ways fool-proofing everything and making nothing customizable. I understand why (it's hard to support everything and ensure no breakage), but this still feels backwards to me.
- personjerry 4y agoWhile this is clever, it's rather difficult to understand and maintain. Imagine having to sift through a CSS file full of > * + * and assorted symbols and figuring out what they mean (and seeing this article, it's clearly not that simple to explain in documentation either).
- alwillis 4y agoIt might help to read the original article that was published nearly 10 years ago [1]. [1]: https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/ https://alistapart.com/article/axiomatic-css-and-lobotomized...
- xigoi 4y agoYou might as well complain that x = y + z is bad code because you have to figure out what the symbols mean.
- zoul 4y agoI am increasingly worried about the “smart” CSS solutions. The spec is already huge, the selectors are hard to read and google, the interplay between various features is devilishly complex. And the CSS community seems to be very fond of these smart hacks where people in the know say “Oh, that’s just Foo’s variation on Bar’s flex owl hammer” and you are left to study the CSS lore for hours to decrypt the two or three letters. I just wish we would value simplicity over cleverness.
- irrational 4y agoI had the exact same sentiment when the arrow function was added to JS. My mind has not been changed in the years since. Clear is always better than clever, arrow functions are not clear (despite the desperate cries to the contrary by complexity loving programmers).
- jraph 4y agoOf all the JS features you are picking the arrow function? Is it the syntax, or the this binding thing that works differently than function expressions / statements you are complaining about? Because the syntax looks somewhat like the function notation in math, and a variation of it is also present in many programming languages, often functional, but also Java since version 8. It's quite widespread and not very bizarre / specific to JS. You'd have mentioned tagged templates [1], I'd have to bow. [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- asplake 4y agoIn case you had to look it up (I did), the lobotomised owl: https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/ https://alistapart.com/article/axiomatic-css-and-lobotomized...
- firstfewshells 4y agoThis is basically a frontend person looking for some validation that they are so smart.
- just-tom 4y agoI think that this sort of CSS is smart being put in some kind of reset.css, being a base for the design, rather than being used occasionally while developing. In both cases, it would be smart to have explicit comments describing what the snippets do.
- mariusmg 4y ago.prose :is(h2 + , h3 + , h4 + *) A person which values their sanity would not write this in CSS.
- ge96 4y agoFor me it would be: border box, flex, the trick to make a square with ::before and content/padding 100%
- 1ko 4y agoyou will love aspect-ratio: 1/1;
- atoav 4y agoAs someone who decidedly likes CSS I think something like this is "too clever". There are some things that should be as boring as possible. Layouts themselves are already a complex matter, so even the most boring and readable css will not be totally boring. When I was younger I also had a phase where I liked to do things like these because I could. Nowadays I do things in a way that doesn't waste my own (or other people's) time by being too clever
- dickjo 4y agoRespectfully, I'm finding the value of this blog post extremely difficult to understand. The author's arguments against gap just don't make sense and I question the logic of their entire design philosophy - the author dismisses gap and says 'The parent is in complete control and the child elements have no say in what gap is at any given moment." ...but that's exactly how a sound design system SHOULD work. Structural components (containers etc) SHOULD be in complete control of child distribution. I simply cannot imagine what a nightmare having to manage margin at an atomic component level for everything would be instead of just spelling out a few container components for them all to live in. Furthermore the resistance to using the two display types that utilise the gap property (flex + grid) is absolutely bizarre. No sane person would avoid these tools as web dev without them is messy and utterly maddening, so this resistance makes no sense at all.
- ibejoeb 4y agoSimply: gap wasn't an option when this was initially conceived. > The author's arguments against gap I don't think it's a argument against gap. It's that this technique is advantageous in some situations. It is stated later on that grid is his choice for bespoke layouts. > what a nightmare having to manage margin at an atomic component level for everything would be instead of just spelling out a few container components This is the essence of the technique. Specifying `* + *` allows controlling the layout of adjacent elements, rather than an atomic element. I think this would all make more sense after reading some of the precedent material: https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/ https://alistapart.com/article/axiomatic-css-and-lobotomized.... (It's actually pretty succinct, so rehashing it here wouldn't add anything.)
- jraph 4y agoThe lines in question: .stack > * + * { margin-block-start: 1.5rem; } I got it immediately because I think I've been doing something similar for a while. I identified the problem it solves. I understand that if you haven't encountered the situation, it's probably hard to decipher. It reads like: apply a top margin to all direct children that are not the first one. I write it like this: .stack > :not(:first-child) { margin-top: 1.5rem; } I probably should start using -block-start. I'll keep my selector though I think. I didn't know about the default value parameter of --var, I'll probably use it too.
- CWIZO 4y agoI haven't done CSS in about 6 years. So I don't understand why you'd ever use OP's version over yours?
- jraph 4y agoFor * + * versus :not(:first-child), I guess it's a matter of style. Maybe they are a bit different in the specificity of the rule, I don't know. margin-block-* and margin-inline-* (versus margin-{top,right,bottom,left}) are more generic and take into account the writing-mode, direction, and text-orientation. https://developer.mozilla.org/en-US/docs/Web/CSS/margin-inline-start https://developer.mozilla.org/en-US/docs/Web/CSS/margin-inli... Notably, for instance, if you want to support both rtl and ltr languages, margin-inline-start (instead of margin-left) will behave correctly and put the margin at the correct side. If you ask me, it's a step towards specifying/conveying the intent and not hard-coding the look.
- chrismorgan 4y agoSpecificity is the difference: * + * is 0,0,0. :not(:first-child) is 0,1,0. :where(:not(:first-child)) would take it back to 0,0,0.
- azhsetiawan 4y agoI write like yours more often and avoid using * selector as much as possible in my CSS. Using :not(:first-child) is more obvious for me and my co-workers who will read that CSS selector.
- lucas_codes 4y agoAll these comments complaining about complexity of the selectors - if you haven't read the MDN page on selectors in the last 5 (10?) years, perhaps now is the time? We were begging for these features for years and it was a nightmare waiting for enough browser support.
- adityaathalye 4y agoShout out to Andy and Heydon for their book Every Layout. It made CSS sensible to me. By no means am I an expert, but I thoroughly enjoy writing CSS using techniques they teach in the book. Somehow, it helps me to think of CSS as a constraint programming system. Combinators are that --- layout constraint directives. Architecturally, I really like the choice of pulling apart CSS in terms of structural definitions (Stack, Box, Switcher etc.), style definitions (applied to leaf nodes as far as possible), and global rules, ratios, and units (e.g. modular scale). I think the system composes beautifully and lets me do a lot with a very small set of core definitions. My personal site uses those techniques: https://www.evalapply.org/static/css/style.css https://www.evalapply.org/static/css/style.css edit: formatting
- p2hari 4y agooh,I was expecting this. @tailwind base; @tailwind components; @tailwind utilities; :)