Hacker News new | ask | show | jobs
by gkaemmer 2280 days ago
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.

2 comments

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

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.
>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.