So, the point is that margins on the UI boundaries of a component are a bad idea. Margins are a visual side-effect, which break the idea of keeping components encapsulated.
It's not anything new really, everybody has experienced pain to try to reuse a component but it's badly encapsulated so it's painful to fit in a new context. It's always worth making it clear and reiterating basic principle under different lights, but this "considered harmful" like you discovered a new law of physics always feels pretentious to me
A simple example with React would be anything using the rebass library (https://rebassjs.org). You can extend its Box/Flex components or do a pass-through (e.g. `({a, b, ...rest}) => <Box {...rest}>{... your stuff here ...}</Box>`), at which point when using your own component you can do `<MyComponentHere marginLeft="0.5em"/>` and have native CSS margins without embedding them into the component or into stylesheets for the component.
You could, but this mental model probably won't be as helpful as thinking of margin as the element pushing its neighbors away (or pushing itself away).
It's hard to define margin without any relation to neighboring elements, it's easy for padding and border. It seems logical that a reusable component shouldn't make assumptions about its neighbors, therefore avoid margins on its boundaries.
Complaints About "Considered Harmful" Titles Considered Harmful...
I like the colorful history of this phrase, and how it usefully marks the following argument as an unbridled assault against purportedly common wisdom, so we can treat it with the huffy disdain with which we should normally treat such cheeky endeavors.
Completely agreed. Margin should only ever be used at the page layout level, where multiple components are being integrated. But spacer components are a terrible idea. Just use CSS.
Curious why you're so opposed to spacer components. In my experience they work quite well--often a designer has specified that two widgets lie a certain distance apart, either vertically or horizontally, and the programmer needs to express that in code. Makes much more sense to use a spacer component than to add a margin to one or both of the widgets themselves.
If responsiveness is what you're after, you can easily make your spacers adaptable to different screen sizes.
Because then the designer comes back and decides to change that spacing by 5% on one page, but not another. And now you're using the same spacer component across your entire application, so you're adding config to a component that needs to be documented and learned by the next developer using it. Instead, just express that spacing in CSS that is specific to a page. Use mixins if you like to set a base default spacing, then extend it whenever needed. Application/component structure should be completely divorced from presentation. It's literally the same problem we had with <table> based layouts.
>In this scenario, you can add props/params to override defaults.
Of course. But why? You're just adding complexity at that point. It's the same problem with frameworks like Bootstrap that use complex combinations of class names for styling. Now instead of having a semantic BEM style class name on the component that I can look up in a stylesheet and modify, I have to memorize an entire framework of esoteric 'col-md-whatever' class names and know how/where/when to apply them. It adds a massive cognitive load beyond just using CSS. In the instance of a custom spacer component described above, I'm now also on the hook for documenting and testing a component that is entirely visual, rather than just writing a couple lines of CSS.
Well then what’s the alternative? Using the same spacer component everywhere is bad because the designer might want to change the spacing in only one spot? Okay. But what if the designer wants to change the spacing in all spots? That’s a much more likely scenario in my experience, but the point is you need to be able to do both.
The point is that layout should be handled at the highest level possible. Have a CSS file at the application shell component level which defines a baseline margin and grid for components, then have individual page component level CSS that can tweak those layouts where needed. Actual UI components should then only ever need to use padding.
Why not let the parent lay its children out? In my experience, a lot of engineers resort to things like spacer components due to not being very good at css. Flex, grid and even table layout should give just about everything needed for all but the most crazy layout needs. With flex and grid, you can often build responsive layouts without needing media queries.
That's exactly what the article is talking about. "Let the parent lay its children out" means "use layout components in the parent". This is what this `Stack` component is: probably a flex container. They use the term "spacer component" but "layout component" would be more accurate and wouldn't trigger all these knee-jerk reactions
My argument is that component isn't needed. The article is basically proposing Parent -> Stack -> Children. I argue the parent should own both its parent roles and the layout roles. The Stack component adds an unnecessary layer IMO. It will probably add an unnecessary DOM node too which is unfortunate. My experience with layout-like components such as this Stack is they often have limitations people work around in bad ways, or sometimes they just end up having props like `columnGap` and basically just end up being a little re-implementation of inline styles. I have pretty much always found just having the parent do layout using standard CSS to be better.
It's a more subtle argument, but a lot of people (me included) think that `<Stack>...</Stack>` is better than `<div class="stack">...</div>`. More readable, more reusable, that's the sort of thing Flutter went with (not a Flutter user personally).
There's no reason it would add unnecessary DOM nodes. You can add styling on top of any component if needed (styled-components is one way but not the only one). Having a `columnGap="small"` is perfectly acceptable for me (`columnGap={3}` too if 3 refers to some scaling, `columnGap="10px"` is bad).
It's similar to the Tailwind approach: have ready-made pieces of UI you can compose. But I also get why you wouldn't like it, and I think any of these approaches work fine enough if you they're used diligently
I agree that spacers are better than margins (and sometimes better than paddings, when people use paddings as margins). Since whitespace is almost always between A and B, ideally the piece of code defining whitespace would be between the pieces of code that are responsible for A and B.
For example, it feels nice to define margin or padding on a <p> element, but what does that mean - distance between two paragraphs? Between paragraph and heading? Between paragraph and bulleted list? Using spacers seems like the only way out of this madness.
> For example, it feels nice to define margin or padding on a <p> element, but what does that mean - distance between two paragraphs? Between paragraph and heading? Between paragraph and bulleted list? Using spacers seems like the only way out of this madness.
Can you explain what spacers are and why they'd be better for this example? Why not use CSS rules that say e.g. "use 1em spacing between p tags", "adding 2em spacing between h1 tags and p tags"?
Yeah, my bad. I realized after writing that comment that pairwise spacing is possible in CSS:
p+p{margin-top:1em}
h1+p{margin-top:2em}
This says more or less directly "1em between p and p, 2em between h1 and p". The values can be changed independently, with no need for collapsing margins and so on. It's a bit unusual though.
That's the approach I use though. Spacer divs is going to lead to lots of repetition and attaching the margin to a single element always leads you to having to undo it when there's an exception later.
It means minimum distance. A key feature is margin is it can collapse. So if paragraphs have 1rem between them, and headings have 2rem above and 1rem below, you won’t wind up with 3rem between the paragraph and the following heading. Padding adds together, and space mechanisms seem like overkill when css can already do the thing in a straightforward way.
What’s befuddling to me about these threads is that they keep trying to make an absolute case. It’s true, I use margin less now that I have grid gap, but there’s still a place for it.
> For example, it feels nice to define margin or padding on a <p> element, but what does that mean - distance between two paragraphs? Between paragraph and heading? Between paragraph and bulleted list? Using spacers seems like the only way out of this madness.
I don't want to be rude but you are completely misunderstanding what CSS and HTML are supposed to do.
1) The <p> tag denotes that the content in the element is a paragraph in the document.
2) The styling is just tell the client (which is typically a browser) how the element is supposed to be styled. It isn't supposed to mean anything in relation to other elements and it isn't supposed to convey meaning.
Generally wherever possible you should try to separate the markup and its styling. You can't always do that, but you should try to.
Lines of 60 characters are at the lower end of what's usually recommended by typographers, but I wouldn't say it's grotesque. A bit too narrow on large screens though.
Margin is a CSS property; using it (or not) is entirely consistent with semantic HTML. The "spacer" component in the article can be achieved with gaps using CSS grid.
You should still write semantic HTML, but that doesn't mean every character in an HTML page has to be directly tied to some meaning that isn't to do with styling.
Google and screen readers aren't going to be confused by you putting a < div class="spacer > < / div > tag in the middle of some < h1 > and < p > tags on a page.
I think coders just need to accept that it's a failed experiment to keep all styling data out of HTML. We've been trying for decades now and it's not practical, especially when you're adding a high level of polish to the presentation of your page while dealing with current web standards.
This also responds well to changes in em size. I like doing it this way because it makes the sizing consistent on mobile vs desktop, as vertical spacing truly should be relative to the font size.
I remember @jpochtar and @gablg1 had a similar take in "Technical lessons from building a compiler startup for 3 years". Under "Don’t trust standards", they wrote "We had no issue w/ using invisible spacer divs instead of the more “semantic” margins or paddings."
I almost didn't read the article because of the horrible title. Anyway, I just want to say this is one of the things I like about elm-ui (a ui-library for the elm programming langauge that replaces HTML/CSS). It has the concepts of spacing and padding. No such thing as margin. https://package.elm-lang.org/packages/mdgriffith/elm-ui/late...
I thought it would be a lean management or economics piece of how low margins are essential to a smooth economy. Or a denouncing thereof. You know, in the days of hospitals being run on just-in-time deliveries.
Oh my sweet summer child. As a pro having done this thing for decades, the industry standard in 2020 is to randomly throw margins, negative margins, and paddings on _everything_ (probably in JS/JSX) in the vicinity of the thing you're trying to position and visually iterate until things looks okay-ish. Probably by a dozen people simultaneously on the project, some of whom may have read an article on CSS once. After a year or two the whole thing is chucked out anyway. And that's all right, it gets the job done.
> randomly throw margins, negative margins, and paddings on _everything_ (probably in JS/JSX) in the vicinity of the thing you're trying to position and visually iterate until things looks okay-ish
I wish this were not the case, but having researched the front page HTML of the 10 top trafficked websites during a new framework selection for a client, this is exactly how things are done.
This made me crack up. I do this all the time and thought it was because I was "bad" at CSS, having not kept up with the times. Is there really no better way in 2020?
Of course there is a better way, but as he/she said most people don't know it. And for a lot of projects that are built to spec once, and maintained with minimal tweaks for a few years (traditional agency projects), the "bad" way is good enough.
If you want a better way for a project that you will have to maintain for a longer time that should be more flexible, I would personally suggest something like BEM[0] + a few best practices (like the one suggested in the post). This will already get you a long way.
I rather like using BEM but have only used for 6 months or so on short projects. What is the “BEM considered harmful” article in 5 years going to say that we don’t know now?
Styling an important or often reused component? You best find a better way.
Adding a tagline to a marketing site or temporary banner? Yea, do whatever you want to get the job done. Just don't let your whole site look like that or you'll have angry teammates.
You make it sound ironical and cynical, but that is actually how things are done in real world. I mean, I admit I have done that sort of thing after I read first article about css after someone required me to move something first time ...
This is reality (business) vs college (academic) lesson (and similar to the tired jokes about brushing off your algorithms books only for interviews).
One time I asked a musician with a degree if I should go back to school for music. I was wondering if he thought it was worth the money and time. He said:
"You can go learn all this stuff and you'll know everything about every song you hear. You'll understand all the underlying structures and how to write it out on paper. And music will become an entirely different thing to you. But guess what? You'll be broke, because that's not what people pay musicians for. They pay musicians to sound good and sell alcohol. All that other stuff only matters to people trying to pass their final."
> As a pro having done this thing for decades, the industry standard in 2020 is to randomly throw margins, negative margins, and paddings on _everything_ (probably in JS/JSX) in the vicinity of the thing you're trying to position and visually iterate until things looks okay-ish.
That's always been the industry standard though. It's a wonder the web works at all.
I have never understood why developers think in absolutes and then try to force this absurdity on other people. It feels immature to me and makes me feel like I am in a prison or an insane asylum.
The quest for absolutes makes a lot of sense to me. I understand they are rare, but when we find them they're a godsend. We have to consider so much at once and there's so many ways to do the same thing that having an absolute can make things much easier.
Haha, brilliant. If I may write the first paragraph:
> Facebook has quietly marked Considered Harmful articles problematic, and that's a good thing.
> When I was a child, my father often took me fishing as a way for us to get out of the house. I remember the dappled early Sunday sunlight playing across the dashboard as we drove up to the lake in our 1998 Subaru Forester, a car whose longevity is likely to be greater than mine. Subaru, as it turns out, tapped into a fundamental part of the American psyche that had, at the time, been left completely untouched out of sheer unawareness.
It's funny how we've come full circle from using CSS the way it was intended to be used to that being "considered harmful" and now we have the Javascript framework equivalent of < img src="spacer.gif" />, an anti-pattern I was using back in 1999.
The reality is that frontend is messy, browsers are still inconsistent with respect to how they treat CSS, and creating new layers of abstraction to handle trivial considerations like adding space on a display are just a way of denying that reality by fixing something that isn't broken.
Creating new, completely useless components to "bring us closer to how designers think" completely flies in the face of separating view from the program layer. And in my experience, "designers think" everyone has a 27" Thunderbolt display, or now increasingly a Pro Display XDR, so I wouldn't really put too much stock in what they think. If you disagree, I would propose spacer.gif as a much more succinct and widely accepted alternative to all the harm being done here.
grid and flexbox are still not carved in stone, so catering to tbe lowest common denominator sometimes means e.g. nesting divs to mimic functionality in another browser
- margin-top inconsistent between Firefox and Chrome in some cases, usually near the start of a container element.
- specifying percentage height for absolutely positioned elements inconsistent in some cases between Firefox and Chrome (bugged in Chrome)
- SVG elements or CSS backgrounds are handled inconsistently by Chrome, Firefox and Safari. Which can depending on the use case can lead to issues like exceeding max-width, failure to apply aspect ratio, or in the case of Safari full page reflows every frame where an SVG is animated.
- Chrome incorrectly renders any scrollable element with backface-visibility: hidden. Requires non-scrollable nesting div.
- Everyone has a different way of specifying custom scrollbars. On some platforms you need to leave room in any scrolling design for a scrollbar which will reliably be an unpredictable width. Chrome and Firefox still have inconsistent non-standardized css proprties. Or (some) Apple users get the self-hiding scrollbar. In practice this needs to be detected and fixed after the fact with Javascript.
- position: sticky unusably broken in Safari
I'm sure there are others, but my point is the browsers are quirky and better to just face it and get over it.
CSS is still a big mess of hacks if you try to have consistent styles across browsers, it's not ie 7 zoom level hacks but you still need various extra properties to make things work.
At almost every job I've had to push back on designs with low contrast and large fixed headers for UI elements. These things look fine on a 27" 4k screen in office lighting, but they're horrible on a 13" laptop with glare from sunlight.
Similar to Facebook's 2G Tuesdays, I'd love to see what designers would come up with if you made them spend one day a week using a 13" 1366x768 200 nit TN screen.
> completely flies in the face of separating view from the program layer.
Why do people stick to this concept like a religion as if it's the only right way that has no tradeoffs though?
If you want a heavily designed look to your website or UI, at some point you're going to have to add annotations to your data for purely presentational reasons either because of limitations with CSS (e.g. there's no way to style the first word of a paragraph with only CSS) or because there's no semantic reason one piece of data should look different from another other than it "looks nicer that way" (e.g. adding a line break in the middle of a heading because you want a two word brand name to appear at the start of a line).
You might be able to avoid presentation-only HTML markup by preprocessing the HTML, modifying the HTML with JavaScript, using some CSS hack, excessive annotations that might never be used (like wrapping all brand names in tags) etc. but is it worth if for this purity of separating data from styling? It has tradeoffs.
I wasn't arguing in favor of separation of view and functionality as gospel. On the contrary, bringing them together can often be more performant _if done correctly._ However, in the context of adding layers of abstraction, I believe it should be a one way trip, ie. we can abstract code functionality from the view, but we should not abstract view functionality into code (and then back into the view at render time). That's like crossing the street twice and ending up where you started.
> I believe it should be a one way trip, ie. we can abstract code functionality from the view, but we should not abstract view functionality into code (and then back into the view at render time). That's like crossing the street twice and ending up where you started.
Can you give an example to illustrate this approach?
This is overengineering, something that should be handled in a view with a CSS class, instead of an abstraction that ends up translating back into a CSS class after the overhead of parsing the abstraction.
I think in the case of your original comment to me, you're arguing something different. You want to bold the first word of an article or apply a line break after the first two words. For a use like that, there's nothing you can do other than to put some kind of view-related functionality in your code, and I agree. But handling that in code isn't fixing something for the sake of fixing it, because there's no way that it could be handled natively by the view in the context of whatever data you pipe into it dynamically.
A CSS class that provides margins to items in a div can be handled natively by the view and should.
>>> e.g. adding a line break in the middle of a heading because you want a two word brand name to appear at the start of a line
However using a in your brand name would likely be a better way to handle this, and makes actual semantic sense in your html. It's also coincidently more robust to changes in your layouts.
Purity for it's own sake is problematic, and definitely sometimes there won't be a good semantic approach. But thinking through cases a little deeper and trying to represent things better semantically can pay off big dividends by increasing the robustness of your solutions.
> However using a in your brand name would likely be a better way to handle this, and makes actual semantic sense in your html. It's also coincidently more robust to changes in your layouts.
I don't see how Brand Name is any more semantic than <div class="no-line-breaks"> Brand Name </div> though. Either way, I can't see how there's a general solution for that example.
- Maybe for another heading, the break in the middle of the brand name will look better because otherwise the previous line would contain only a single word.
- Or the approach works okay for short brand names but not very long ones (e.g. Department for Work and Pensions).
- Or maybe for one heading we want a break only because otherwise the brand name is going to overlap with the eyes of a person in a background photo.
CSS doesn't even have anything built in to do nice looking justified paragraphs yet (like LaTeX has), let alone simple stuff like dealing with text widows and text orphans.
You could conceivably come up with a general algorithm that encodes some of the design heuristics above but that's in the realms of automating graphic design and there's always going to be exceptions.
My point is, there's no clean separation between content/data and styling if you want your data presented in a very specific way. For heavily designed pages, this is underscored by it always being unavoidable that you'll end up modify the text content because you want it to look more presentable e.g. changing a heading so it to fits in a tight space or line breaks in a pleasing way.
I think the answer is to give up on wanting things to be presented in a specific way. The user may want, or need, for it to be presented a different way anyway. So just provide the content and let the user agent lay it out as the user needs or wants it.
> I think the answer is to give up on wanting things to be presented in a specific way.
I can't see how that's ever going to happen. You're going to tell Apple or a professional graphic designer to not care about small details in the way their pages are presented? Raw data and semantics isn't the single most important thing in all cases.
Yeah, not going to happen anytime soon. Branding is such a big part of every company and the bigger the company gets, the more important it will get. People spend a fortune just to control how every milimeter of their product looks and feels.
This is a honourable vision, sure, but also a completely unrealistic one.
Exactly my thoughts, I had to check twice make sure the article was not parody. This will probably come across as provocative, but it's my honest feeling: I'm glad I got out of whatever frontend development has become.
You will have to elaborate I think. The article seems to me to simply be saying that rather than an individual component being responsible for the margins around itself it should not make assumptions about the context it is used in and should instead let the context or container decide the margins/spacing. That seems sensible does it not? I don't think it really has anything to do with components or using CSS in a non-standard way, it's just about good structure. Why do you think it's so crazy?
The article does not suggest any of those ideas you think it presents (especially, it does NOT suggest an react equivalent of "spacer.gif") and your comment completely misses the point of the article.
> completely flies in the face of separating view from the program layer
HTML is the view layer. The "program" layer is JS manipulating JSON (ultimately fetched from a DB).
Separating HTML and CSS made sense when content lived in HTML, and styling lived in CSS. Content hasn't lived in HTML in a long time— it lives in a DB now. (Maybe markdown if you're making a static site.) Separating HTML from CSS is separating view layer from view layer— just an unnecessary and expensive indirection
Beware - what this article calls a "spacer component" is nothing like <img src="spacer.gif">. Rather it is a container that specifies the spacing between its child components.
The article just argues that spacing between sibling components should be specified by the container rather than by the individual components.
This makes sense in some contexts where you have a uniform spacing between components. In other contexts, like an article with headers and paragraphs, it doesn't make sense. But you probably wouldn't use React for that in the first place.
In CSS you can do both and the article is not pro or con CSS in any sense.
I semi-agree with the point being made, but I don't like the solution. Spacer components isn't the solution, IMO, separating the reusable styles from one time styles is.
so instead of:
<div class="link"/>
<div class="spacer"/>
<div class="link"/>
<div class="spacer"/>
<div class="link"/>
We should be doing:
<div class="link space-right"/>
<div class="link space-right"/>
<div class="link"/>
This allows the reusable styles to be reused and the spacing to be one off.
P.S. since I'm more of a react/styled-components kind of guy, this is how I would look to do it there
The longer I spend engineering, the more I just want to get the job done and get it over with. I've built, and will continue to build, strongly-opinionated frameworks and platforms based on my experience. But this week's silver bullet is next week's anti-pattern: mostly because of a misunderstanding of when, how, and where to apply design patterns.
Truthfully, it's increasingly my opinion that design patterns (and by extension, anti-patterns) only exist in the context of focused, internally consistent systems architected by a small group of individuals and not a committee. Rails, especially early on, is a great example. Actually -- a huge chunk of programming languages are built this way. The web, however, is designed by committee.
With this framing, "avoiding margins" works for the way Max builds design systems -- and from what I know, he's very talented and the team(s) that work with him should adhere to the systems he constructs. I'd love to see an implementation of an entire framework / design system that avoids margins -- something like Tailwind CSS. I do not, however, really believe this is broadly applicable advice. Most people are just trying to ship something that looks nice, and margins can be overwritten and adjusted easily.
NOTE: I have components I've written that have margins I have to overwrite nearly universally, but can't remove because of other UIs relying on the margin behavior. So I understand where the argument comes from. It's just -- I'd have a hard time if anybody tried to pick a bone with a software engineer on the team about the use of a margin if the initial intention was good / legitimate.
To chime in on good intentions. Some branding guidelines specify "this logo must always have 20px of space around it".
Using margin will guarantee it'll have at least 20px and likely only 20px top and bottom with the way margin collapsing works with CSS. Padding or spacers would just add potentially more space than the minimum design requirement.
Can't you just override margin with an "!important" rule? I disagree with this article's exhortation. Cascading style sheets have priorities and override mechanisms for a reason.
Sorry to be unpleasant... but DUH. This was true long before React. It's a core idea in assembled layouts, that is to say all layouts.
Margins need to come from the assembling component, rather than the detail item. Spacing requires awareness of multiple elements, which you usually don't have internally.
125 comments
[ 2.3 ms ] story [ 195 ms ] threadIt's not anything new really, everybody has experienced pain to try to reuse a component but it's badly encapsulated so it's painful to fit in a new context. It's always worth making it clear and reiterating basic principle under different lights, but this "considered harmful" like you discovered a new law of physics always feels pretentious to me
It's hard to define margin without any relation to neighboring elements, it's easy for padding and border. It seems logical that a reusable component shouldn't make assumptions about its neighbors, therefore avoid margins on its boundaries.
That said, I almost didn't read the post simply because "Considered Harmful" is the most obnoxious title format I know of.
I like the colorful history of this phrase, and how it usefully marks the following argument as an unbridled assault against purportedly common wisdom, so we can treat it with the huffy disdain with which we should normally treat such cheeky endeavors.
If responsiveness is what you're after, you can easily make your spacers adaptable to different screen sizes.
Of course. But why? You're just adding complexity at that point. It's the same problem with frameworks like Bootstrap that use complex combinations of class names for styling. Now instead of having a semantic BEM style class name on the component that I can look up in a stylesheet and modify, I have to memorize an entire framework of esoteric 'col-md-whatever' class names and know how/where/when to apply them. It adds a massive cognitive load beyond just using CSS. In the instance of a custom spacer component described above, I'm now also on the hook for documenting and testing a component that is entirely visual, rather than just writing a couple lines of CSS.
There's no reason it would add unnecessary DOM nodes. You can add styling on top of any component if needed (styled-components is one way but not the only one). Having a `columnGap="small"` is perfectly acceptable for me (`columnGap={3}` too if 3 refers to some scaling, `columnGap="10px"` is bad).
It's similar to the Tailwind approach: have ready-made pieces of UI you can compose. But I also get why you wouldn't like it, and I think any of these approaches work fine enough if you they're used diligently
For example, it feels nice to define margin or padding on a <p> element, but what does that mean - distance between two paragraphs? Between paragraph and heading? Between paragraph and bulleted list? Using spacers seems like the only way out of this madness.
Can you explain what spacers are and why they'd be better for this example? Why not use CSS rules that say e.g. "use 1em spacing between p tags", "adding 2em spacing between h1 tags and p tags"?
What’s befuddling to me about these threads is that they keep trying to make an absolute case. It’s true, I use margin less now that I have grid gap, but there’s still a place for it.
And protip: Whenever you have a CSS problem, think: "Oh, I'll just use negative margins!"
I don't want to be rude but you are completely misunderstanding what CSS and HTML are supposed to do.
1) The <p> tag denotes that the content in the element is a paragraph in the document.
2) The styling is just tell the client (which is typically a browser) how the element is supposed to be styled. It isn't supposed to mean anything in relation to other elements and it isn't supposed to convey meaning.
Generally wherever possible you should try to separate the markup and its styling. You can't always do that, but you should try to.
Google and screen readers aren't going to be confused by you putting a < div class="spacer > < / div > tag in the middle of some < h1 > and < p > tags on a page.
I think coders just need to accept that it's a failed experiment to keep all styling data out of HTML. We've been trying for decades now and it's not practical, especially when you're adding a high level of polish to the presentation of your page while dealing with current web standards.
The only other case where I can imagine an element being improperly spaced is when its parent’s padding is messed up.
https://twitter.com/wongmjane/status/1242370883320049664?s=2...
I remember @jpochtar and @gablg1 had a similar take in "Technical lessons from building a compiler startup for 3 years". Under "Don’t trust standards", they wrote "We had no issue w/ using invisible spacer divs instead of the more “semantic” margins or paddings."
https://medium.com/@gabriel_20625/technical-lessons-from-bui...
It's just a tool to be used. Sure it can be harmful if you don't understand it.
I wish this were not the case, but having researched the front page HTML of the 10 top trafficked websites during a new framework selection for a client, this is exactly how things are done.
If you want a better way for a project that you will have to maintain for a longer time that should be more flexible, I would personally suggest something like BEM[0] + a few best practices (like the one suggested in the post). This will already get you a long way.
[0]: http://getbem.com/
Styling an important or often reused component? You best find a better way.
Adding a tagline to a marketing site or temporary banner? Yea, do whatever you want to get the job done. Just don't let your whole site look like that or you'll have angry teammates.
One time I asked a musician with a degree if I should go back to school for music. I was wondering if he thought it was worth the money and time. He said:
"You can go learn all this stuff and you'll know everything about every song you hear. You'll understand all the underlying structures and how to write it out on paper. And music will become an entirely different thing to you. But guess what? You'll be broke, because that's not what people pay musicians for. They pay musicians to sound good and sell alcohol. All that other stuff only matters to people trying to pass their final."
That's always been the industry standard though. It's a wonder the web works at all.
Just use the correct tool for the given task.
> Facebook has quietly marked Considered Harmful articles problematic, and that's a good thing.
> When I was a child, my father often took me fishing as a way for us to get out of the house. I remember the dappled early Sunday sunlight playing across the dashboard as we drove up to the lake in our 1998 Subaru Forester, a car whose longevity is likely to be greater than mine. Subaru, as it turns out, tapped into a fundamental part of the American psyche that had, at the time, been left completely untouched out of sheer unawareness.
The reality is that frontend is messy, browsers are still inconsistent with respect to how they treat CSS, and creating new layers of abstraction to handle trivial considerations like adding space on a display are just a way of denying that reality by fixing something that isn't broken.
Creating new, completely useless components to "bring us closer to how designers think" completely flies in the face of separating view from the program layer. And in my experience, "designers think" everyone has a 27" Thunderbolt display, or now increasingly a Pro Display XDR, so I wouldn't really put too much stock in what they think. If you disagree, I would propose spacer.gif as a much more succinct and widely accepted alternative to all the harm being done here.
Insert Game of Thrones too dark meme here...
Are they? CSS seems to be rock-solid and consistent now. The days of IE6 randomly breaking the box model are far behind us.
- margin-top inconsistent between Firefox and Chrome in some cases, usually near the start of a container element.
- specifying percentage height for absolutely positioned elements inconsistent in some cases between Firefox and Chrome (bugged in Chrome)
- SVG elements or CSS backgrounds are handled inconsistently by Chrome, Firefox and Safari. Which can depending on the use case can lead to issues like exceeding max-width, failure to apply aspect ratio, or in the case of Safari full page reflows every frame where an SVG is animated.
- Chrome incorrectly renders any scrollable element with backface-visibility: hidden. Requires non-scrollable nesting div.
- Everyone has a different way of specifying custom scrollbars. On some platforms you need to leave room in any scrolling design for a scrollbar which will reliably be an unpredictable width. Chrome and Firefox still have inconsistent non-standardized css proprties. Or (some) Apple users get the self-hiding scrollbar. In practice this needs to be detected and fixed after the fact with Javascript.
- position: sticky unusably broken in Safari
I'm sure there are others, but my point is the browsers are quirky and better to just face it and get over it.
Similar to Facebook's 2G Tuesdays, I'd love to see what designers would come up with if you made them spend one day a week using a 13" 1366x768 200 nit TN screen.
Why do people stick to this concept like a religion as if it's the only right way that has no tradeoffs though?
If you want a heavily designed look to your website or UI, at some point you're going to have to add annotations to your data for purely presentational reasons either because of limitations with CSS (e.g. there's no way to style the first word of a paragraph with only CSS) or because there's no semantic reason one piece of data should look different from another other than it "looks nicer that way" (e.g. adding a line break in the middle of a heading because you want a two word brand name to appear at the start of a line).
You might be able to avoid presentation-only HTML markup by preprocessing the HTML, modifying the HTML with JavaScript, using some CSS hack, excessive annotations that might never be used (like wrapping all brand names in tags) etc. but is it worth if for this purity of separating data from styling? It has tradeoffs.
Can you give an example to illustrate this approach?
This is overengineering, something that should be handled in a view with a CSS class, instead of an abstraction that ends up translating back into a CSS class after the overhead of parsing the abstraction.
I think in the case of your original comment to me, you're arguing something different. You want to bold the first word of an article or apply a line break after the first two words. For a use like that, there's nothing you can do other than to put some kind of view-related functionality in your code, and I agree. But handling that in code isn't fixing something for the sake of fixing it, because there's no way that it could be handled natively by the view in the context of whatever data you pipe into it dynamically.
A CSS class that provides margins to items in a div can be handled natively by the view and should.
However using a in your brand name would likely be a better way to handle this, and makes actual semantic sense in your html. It's also coincidently more robust to changes in your layouts.
Purity for it's own sake is problematic, and definitely sometimes there won't be a good semantic approach. But thinking through cases a little deeper and trying to represent things better semantically can pay off big dividends by increasing the robustness of your solutions.
I don't see how Brand Name is any more semantic than <div class="no-line-breaks"> Brand Name </div> though. Either way, I can't see how there's a general solution for that example.
- Maybe for another heading, the break in the middle of the brand name will look better because otherwise the previous line would contain only a single word.
- Or the approach works okay for short brand names but not very long ones (e.g. Department for Work and Pensions).
- Or maybe for one heading we want a break only because otherwise the brand name is going to overlap with the eyes of a person in a background photo.
CSS doesn't even have anything built in to do nice looking justified paragraphs yet (like LaTeX has), let alone simple stuff like dealing with text widows and text orphans.
You could conceivably come up with a general algorithm that encodes some of the design heuristics above but that's in the realms of automating graphic design and there's always going to be exceptions.
My point is, there's no clean separation between content/data and styling if you want your data presented in a very specific way. For heavily designed pages, this is underscored by it always being unavoidable that you'll end up modify the text content because you want it to look more presentable e.g. changing a heading so it to fits in a tight space or line breaks in a pleasing way.
I can't see how that's ever going to happen. You're going to tell Apple or a professional graphic designer to not care about small details in the way their pages are presented? Raw data and semantics isn't the single most important thing in all cases.
This is a honourable vision, sure, but also a completely unrealistic one.
HTML is the view layer. The "program" layer is JS manipulating JSON (ultimately fetched from a DB).
Separating HTML and CSS made sense when content lived in HTML, and styling lived in CSS. Content hasn't lived in HTML in a long time— it lives in a DB now. (Maybe markdown if you're making a static site.) Separating HTML from CSS is separating view layer from view layer— just an unnecessary and expensive indirection
The article just argues that spacing between sibling components should be specified by the container rather than by the individual components.
This makes sense in some contexts where you have a uniform spacing between components. In other contexts, like an article with headers and paragraphs, it doesn't make sense. But you probably wouldn't use React for that in the first place.
In CSS you can do both and the article is not pro or con CSS in any sense.
so instead of:
<div class="link"/>
<div class="spacer"/>
<div class="link"/>
<div class="spacer"/>
<div class="link"/>
We should be doing:
<div class="link space-right"/>
<div class="link space-right"/>
<div class="link"/>
This allows the reusable styles to be reused and the spacing to be one off.
P.S. since I'm more of a react/styled-components kind of guy, this is how I would look to do it there
const Link = styled.div`
//... styles
` const LinkWithSpacer = styled(Link)`
//... margin
`
<LinkWithSpacer />
<LinkWithSpacer />
<Link />
Truthfully, it's increasingly my opinion that design patterns (and by extension, anti-patterns) only exist in the context of focused, internally consistent systems architected by a small group of individuals and not a committee. Rails, especially early on, is a great example. Actually -- a huge chunk of programming languages are built this way. The web, however, is designed by committee.
With this framing, "avoiding margins" works for the way Max builds design systems -- and from what I know, he's very talented and the team(s) that work with him should adhere to the systems he constructs. I'd love to see an implementation of an entire framework / design system that avoids margins -- something like Tailwind CSS. I do not, however, really believe this is broadly applicable advice. Most people are just trying to ship something that looks nice, and margins can be overwritten and adjusted easily.
NOTE: I have components I've written that have margins I have to overwrite nearly universally, but can't remove because of other UIs relying on the margin behavior. So I understand where the argument comes from. It's just -- I'd have a hard time if anybody tried to pick a bone with a software engineer on the team about the use of a margin if the initial intention was good / legitimate.
Using margin will guarantee it'll have at least 20px and likely only 20px top and bottom with the way margin collapsing works with CSS. Padding or spacers would just add potentially more space than the minimum design requirement.
Margins need to come from the assembling component, rather than the detail item. Spacing requires awareness of multiple elements, which you usually don't have internally.