Readit News logoReadit News
tristanperry · 4 years ago
I do agree generally, but it's funny that the suggested solution (spacers) are basically back to the old 1px transparent gif trick from the 90s/early 00s.

Nothing wrong with the suggestion, but it's just ironic that we seem to be coming full circle again.

Next we'll probably have posts extolling <Table> components for layouts ;)

ratww · 4 years ago
> I do agree generally, but it's funny that the suggested solution (spacers) are basically back to the old 1px transparent gif trick from the 90s/early 00s.

They aren't the same thing. Check the link in the article [1]. It is using regular CSS, and some of those components use more modern things like Grids.

They also aren't applied between components like old element-spacers. Component Spacers have much more in common with regular margin/padding than with 90s spacers.

[1] https://seek-oss.github.io/braid-design-system/components/St...

armandososa · 4 years ago
> it's funny that the suggested solution (spacers) are basically back to the old 1px transparent gif trick

Not really. The Stack component he uses as an example is actually just a thin abstraction over some reusable css. In plain html, it could look like

    <section class="stack stack--space-3">
        <article class="item">...</article>
        <article class="item">...</article>
        <article class="item">...</article>
    </section>
There are no "spacer gifs" anywhere, it's only that you're lifting the margin responsibility to the parent. I may be wrong, but I think the whole stack concept is borrowed from SwiftUI.

That said, I've recently started using actual spacer divs that are more similar to the spacer gifs of yore, you mentioned. So I could do things like:

    <section>
        <div class="vertical-spacer-2"/>
        <article class="item">...</article>
        <div class="vertical-spacer-1"/>
        <article class="item">...</article>
        <div class="vertical-spacer-1"/>
        <article class="item">...</article>
        <div class="vertical-spacer-2"/>
    </section>
Having been alive during the whole semantic web era, that feels very wrong to me. But it works like a charm to keep your code consistent with a design system which seems like a more noble endeavor than to write html that makes more sense to machines (which was, if I remember correctly, the objective of the semantic web).

arcticbull · 4 years ago
Stacks started in UIKit (UIStackView) and before that were cribbed from Android, IIRC.
timeon · 4 years ago
Tendency towards semantic web is unfortunately dead. Now you have simple blogs rendered by shadow DOM components. Even with templates separation of template and code was ideal - now you have 'reusable components' with templates all over the place. Functional programming has its place, but I'm not sure if everywhere. (You can separate code from templates even with FP and React - but often it is not the case).
tambourine_man · 4 years ago
>Tendency towards semantic web is unfortunately dead.

Not dead, but under severe attack. We can and will fightback

7sidedmarble · 4 years ago
I don't think you know what Shadow DOM means. Shadow DOM is not just another virtual DOM. It is a very specific thing built into browsers used only for HTML Custom Elements.

It is not very popular. React, Vue, etc., do not use the Custom Element spec.

jerrycruncher · 4 years ago
Concurrent with spacer.gif, there was also a `<spacer type="block">`[1] tag that was in use at the time.

Working at a boutique design shop back then, I remember trying endless combinations of the spacer tag along with spacer gifs to try to ship layouts that were at least semi (and hopefully mostly) consistent cross-browser.

Having lived through those web dev dark ages, I'm pretty baffled by the resurgence of 'markup as styling'.

[1] https://www.tutorialspoint.com/html/html_spacer_tag.htm

thrower123 · 4 years ago
Time is a flat circle, and we're just going to be rehashing the same ideas endlessly every five years until the heat death of the universe.
tambourine_man · 4 years ago
It's more like a spiral if you adjust the perspective.

We'll revisit old ideas from time to time after going the opposite extreme, but never in the same way.

ratww · 4 years ago
Spacer components and spacer elements are not the same idea, though, far from it.
dmix · 4 years ago
> but it's funny that the suggested solution (spacers) are basically back to the old 1px transparent gif trick from the 90s/early 00s.

I have to agree with others. It is not the same as 1px spacer hacks at all.

j0ej0ej0e · 4 years ago
My company recently had a FE candidate supply a test using tables.
MarcellusDrum · 4 years ago
Serious question: What is inherently wrong with using Tables for organizing simple layouts? Is it frowned upon just because it is a "hacky" way of doing stuff?
dmix · 4 years ago
There’s still a place for tables in some use cases. But that use case is thin.

Dead Comment

roman-holovin · 4 years ago
That's very reductionist approach. Sure, margin is a sharp tool and you need to use it responsibly.

I avoid putting margins on "first"-level selector.

So instead of

    .button {
      margin-left: 16px
    }
I do

    .parent > .button {
      margin-left: 16px
    }
Difference is that I can reuse '.button' elsewhere without modifications.

Another point to consider is that margin is not the only CSS property that affects layout. Both grid, flexbox and 'position' properties should be used with same care. And approach I highlighted above is usually good enough.

For margin specifically there is also a "owl" selector that makes is a bit easier to manage

    .parent > * + * {
      margin-top: 16px; // OR
      margin-left: 16px;
    }

goldenkey · 4 years ago
I hadn't heard of the owl selector for selecting :not(:first-child). Thank you for teaching me something new!
extra88 · 4 years ago
The term was coined by Heydon Pickering [0]. He's great, also responsible for the useful site Inclusive Components [1] and one of the authors of Every Layout [2].

[0] https://alistapart.com/article/axiomatic-css-and-lobotomized...

[1] https://inclusive-components.design

[2] https://every-layout.dev

Kavelach · 4 years ago
Note that the owl selector is pretty slow when it comes to being processed by browsers. If you use it sparingly, it shouldn't be so bad, but leave it all over the place, and you'll see the impact
the_other · 4 years ago
You have the same understanding as the OP. The difference is that the OP is working on a component-based framework. In such a framework, it makes sense to declare the rule defining child margins *in* the parent component's code, not in the child's code.
city41 · 4 years ago
But why do it with extra elements? The child should accept a class or possibly styles and the parent decides what those are.

Child directly styles itself with color, font, internal layout, etc

Parent positions child with flex box, grid, margin or absolute positioning. Spacer elements are not needed at all.

mizzao · 4 years ago
Is there a easy way to do this with a utility framework like tailwind? It just makes it so tempting to throw the margin on a component.
roman-holovin · 4 years ago
This is one reason I'm not really into utility frameworks. They are able to deal with "appearance" part of the CSS just fine, but layout part is too rigid and inflexible.

You can use plain old CSS for layout purposes and mix it with utility classes for appearance.

You can do:

    <div class="actions">
        <button class="h-10 px-6 font-semibold rounded-md bg-black text-white" type="submit">
          Buy now
        </button>
        <button class="h-10 px-6 font-semibold rounded-md border border-gray-200 text-gray-900" type="button">
          Add to bag
        </button>
      </div>
And then:

    .actions {
        display: flex;
        justify-content: flex-end;
        align-items: center;
    }

    .actions > * + * {
        margin-left: 16px; // or better use var from tailwind to set sizes consistently.
        @apply: ml-5; // or do this https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply
    }
This should combine those techniques, but I haven't used it in practice. And I'm sure in this case you will be labeled as heretic by both people who don't use utility frameworks and those who do ;)

deergomoo · 4 years ago
Tailwind has gap-[0] for flex and grid, and space-[0] for the “owl selector” approach.

[0]: https://tailwindcss.com/docs/gap

[1]: https://tailwindcss.com/docs/space

lelandfe · 4 years ago
Needs (2020) in the title. Original discussion, 123 comments: https://news.ycombinator.com/item?id=22676442

Anyway, considered harmful articles considered harmful.

There is a time and place for margins. Being thoughtful with them is a better approach than "banning margin from all components."

Should I really ban the use of `margin-left: auto` when positioning my flexed elements? I don't think this article is actually advocating for that, but a novice reader may.

HelloNurse · 4 years ago
Being thoughtful is a better approach than "considered harmful" clickbait in any situation.

Regarding CSS margins, they are part of the box model even if certain stylesheets neglect them, and the only conflicts they can be involved in are easily solved (a rule for "container x" is more specific than a rule for "x" and can override margins, particularly with parent padding, in special cases) and they highlight genuine design defects: trying to use a component both with and without its "natural" margins (without adding appropriate classes or wrapping containers), trying to specify conflicting margins, trying to fit variable-sized content inside fixed-size containers by messing with the content's required margins, and so on.

underwater · 4 years ago
A margin is contextual, so a reusable component shouldn't have them.

It's a shame that CSS doesn't allow the parent element to define how spacing around the child elements should work.

necovek · 4 years ago
I thought you could do that with eg.

  parent > * {
  ...
  }
There might be things missing to achieve whatever result you desire, but CSS does allow a parent element to define how spacing (and any other styling) works for child elements.

5560675260 · 4 years ago
We can do this now with flexbox and grid. Spacer component from the article can be implemented with https://developer.mozilla.org/en-US/docs/Web/CSS/gap
eyelidlessness · 4 years ago
> It's a shame that CSS doesn't allow the parent element to define how spacing around the child elements should work.

It really would be a shame if CSS didn’t have child selectors, and if they weren’t more specific than bare selectors.

spaniard89277 · 4 years ago
You can do it with selectors, also with flexbox and the gap property.
Xevi · 4 years ago
Out of curiosity, why do you need to use "margin-left: auto" when working with flexbox items? What is it that you're trying to do, which can't be solved with "justify-content" and "align-items"?
djrockstar1 · 4 years ago
Not OP but I had a scenario where I had a row with a variable number of items, left-aligned, and then the final item had to be right-aligned. "margin-left: auto" on the final item achieves that effect.
dmix · 4 years ago
Still a useful article / discussion that belongs on HN IMO.
au-arms · 4 years ago
Clever, but this smells like a performance anti-pattern. Adopting this means you could, at worst, add 4 spacer divs per component. While most sites may never really feel a sting, for complex apps where reusability is a larger concern you've doubled to quadrupled the size of an already large DOM and you will be hit a death-by-one-thousand-cuts situation.

Now you've got more...

- html over the wire

- html to parse for first render

- DOM nodes to mount/unmount

- memory usage from excess DOM

- costly layouts due to extra nodes

- lighthouse complaints of an excessively large DOM

Otherwise a clean approach. Perhaps it could be solved at compile time or some other jsx -> CSS abstraction to maintain DX.

FinalBriefing · 4 years ago
I saw a blog post a while back from a React developer who did this. They didn't use padding or margins, just `<div>` elements with an exact height and width. I fail to see any benefits of doing it that way...just learn and use CSS.

I'm not sure if that's what this post is suggesting, though.

s-lambert · 4 years ago
Why do you need to add spacer divs? As long as the child components accept classes as props then the styling comes from the parent but is still applied on the children.
FloNeu · 4 years ago
You can also apply margin via element and nth-child selectors, just as a note... Also - custom/shadow dom elements should allow classes - I think it doesn't work in angular yet - but should arrive in the next version(?). Also you could just use ::before ::after pseudo selectors instead of divs...
smarkov · 4 years ago
If you're worried about a few additional elements your DOM is already too big and you have bigger issues to worry about.
thomasahle · 4 years ago
Can't you just use the spacing properties of the container? Like flexbox's space-around and space- between?
au-arms · 4 years ago
You can, however the lack of constraints on the spacing can make it difficult to match strict design systems. The dependence the spacing creates on the parent & child dimensions can lead to undesirable edge cases as well for dynamic/responsive content.
bryanrasmussen · 4 years ago
I also think repaints are probably more expensive given this solution.
au-arms · 4 years ago
More expensive with or without the spacer components?

Dead Comment

andrewingram · 4 years ago
I think "spacer components" is a bit confusing and not really the message someone should take away from this. I think it's better to say something like "Make parent components responsible for managing spacing around their children", not as catchy I admit.
vore · 4 years ago
I think the main bugbear of margins that the article doesn't mention is margin collapse: I personally don't find the rules super intuitive and I would rather just be explicit with spacing than have the browser collapse things together!
jicea · 4 years ago
Agree, collapsing margins are counterintuitive, and only applied to top and bottom margin. It’s really surprising how many people don’t know it’s a thing and fight the box model. If you think you’re constantly fighting layout, try to read the MDN docs [1] with a fresh eye. I was guilty to think I needn’t learn CSS, and reading the MDN really help me.

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

bhk · 4 years ago
What's really surprising is how many people do know that margin collapse is a thing, but haven't fully understood all of the implications, so they still get mystified by some unintended consequence.

I don't think that "go read all the MDN docs" is a very useful suggestion. More useful is something like the following, which I don't think you will find anywhere in MDN:

When an element's top or bottom margin collapses with its parent, this may affect the position of the parent, because the minimum of the child and parent's margin will be used to position the parent. (MDN says the child element's margin will fall "outside the parent", but it is not clear that it will be used during layout to place the parent.)

The bigger problem is that CSS is just so complicated and arbitrary. Consider the rule for collapsing margins with parents, from MDN:

> If there is no border, padding, inline part, block formatting context created, or clearance to separate the margin-top of a block from the margin-top of one or more of its descendant blocks; or no border, padding, inline content, height, or min-height to separate the margin-bottom of a block from the margin-bottom of one or more of its descendant blocks, then those margins collapse.

They list five different factors that prevent collapse, one of which ("block formatting context created") is a link to a page that defines it in terms of 15 different constructs or situations in CSS.

On top of that, it appears that the MDN text is in error, because it lists intervening "height" as something that prevents bottom margin collapse, but not top margin collapse (when in fact it does).

cies · 4 years ago
This is according to me the real issue. Besides this unintuitive collapsability margins, there is only one difference between margin and padding: the edges/border of the background color.

It's the unintuitive collapsability that messes up margins.

pcurve · 4 years ago
I almost feel it should be written out of the spec, because a lot of people still don't understand it, designers and developers. And design tools like Sketch or Figma will never implement it in their tools.
jacobp100 · 4 years ago
If you don’t want the margins to collapse, set the container to display: flex.
scns · 4 years ago
One way around this is to only define margins at the end of the container.
bhk · 4 years ago
Bottom margins can still collapse with those of a parent container.
madmod · 4 years ago
Margin is generally more desirable than padding imo. Component/element knows the content it contains and uses margins to require a minimum amount of spacing. It avoids the need to make decisions on the spacing between every combination of components.

Padding only works if you know everywhere your component might be used or don't mind remaking spacing decisions every time you use it. In my experience minimizing code needed for each use of a component leads to more coherently styled interfaces, particularly on larger or faster moving teams.

x3ro · 4 years ago
The author is arguing exactly that: remake spacing decisions every time you use a component, because that’s what many designers (most?) do. This is also true in my experience.
necovek · 4 years ago
There are several types of designers, and even on the web itself, several different things you might be designing. Designing a text medium (eg. a blog) should have more focus on semantic tagging compared to a SPA where you probably want an entirely different approach (and where talk of "components" makes more sense).

I like TeX's box model over CSS which allows for easier "smart" spacing (look up hglue, vglue, hskip, vskip, and eg. care for orphans when typesetting etc.) and smarter column alignment (trivial alignment on decimal point in tables).

While I'd never call myself a designer, I've done plenty of TeX (print and PDF) publications that people have commended for usability and appearance.

HelloNurse · 4 years ago
I want CSS to make spacing decisions so that I don't have to, and a system where graphical elements look good by default because they come with appropriate margins and containers adapt to what I want them to contain (e.g. by shrinkwrapping the content or by switching between different numbers of columns or rows) is more useful than a non-system that looks bad unless I keep many tedious ad-hoc specifications consistent.

Moreover,

> Margin breaks component encapsulation. A well-built component should not affect anything outside itself.

Definitely not, margins are an essential part of a component, like a garden around a house, and they make components "usable in any context or layout" (unless the context or layout is stupidly overcomplicated).

eyelidlessness · 4 years ago
> remake spacing decisions every time you use a component

I’ve worked with several awesome designers and they all appreciated when I told them this is untenable.

diordiderot · 4 years ago
The word padding isn't in the article...

He reccomends spacing at the parent

Deleted Comment

locallost · 4 years ago
The point about not having it in a component is valid. It happens all the time that a margin on a component is different based on context. But there is no need to make it any more complicated than a margin -- just add the margin externally and if your framework can't do that, add a wrapper and put the margin there.