This one's a small build — a blog preview card, a Frontend Mentor challenge. Nothing about it is complicated on the surface: an image, a tag, a date, a title, a description, an author. But two small pieces of it didn't work the way I expected, and both times the reason why turned out to matter more than the fix itself.
The span that wouldn't stay small
The card has a tag on it — "Learning" — styled to look like a little yellow pill sitting above the title. I reached for a <span> for it, because a span is inline by default. Inline elements only take up as much width as their content needs. That's the whole reason to use one here: I wanted a tag-shaped box, not a bar running across the card.
Except when I built it, it didn't behave like that. The tag stretched the full width of the card.
The card is a flex container with flex-direction: column. I knew that. What I hadn't connected was that flex changes the rules for its children — inside a flex container, children stretch to fill the cross axis by default, regardless of what they'd normally do outside of one. display: inline doesn't mean anything once an element becomes a flex item. The span wasn't behaving like a span anymore; it was behaving like a flex child, and flex children stretch unless told otherwise.
The fix is one line:
.card__tag {
align-self: flex-start;
}
align-self overrides the container's default alignment for just that one element — shrink to fit your content, ignore what everyone else is doing. Once I added it, the tag went back to looking like a tag.
The part worth remembering isn't the fix. It's that "I know what this element normally does" stopped being true the moment I put it inside a flex container. Context changes behavior, even for something as basic as inline vs block.
The heading that couldn't take a hover
The title needed a hover effect — the text should change color when you mouse over it, since it's a link to the full article. I built it the straightforward way first:
<h1 class="card__title">HTML & CSS foundations</h1>
An <h1> because it's the piece's main heading. That part wasn't in question. But once I tried to add the hover behavior to it, something felt off, and it took some reasoning to figure out why.
<h1> elements aren't interactive. They don't receive keyboard focus. A mouse user would see the color change on hover just fine — but a keyboard user tabbing through the page would get nothing, no visual signal that this thing does anything at all. A screen reader wouldn't announce it as a link either, because it isn't one. It's heading text that happens to look clickable to someone using a mouse, and that's it. Anyone not using a mouse would have no way to know.
If something responds to hover, it should be something that can actually be interacted with — which meant an <a> tag, not styling applied to a heading. But I didn't want to just wrap the whole <h1> in a link and call it done, because that changes where the hover boundary sits: hover the empty space around the text, not just the text, and it still triggers. I wanted the interactive zone to match the text itself.
So the anchor goes inside the heading, not around it:
<h1 class="card__title"><a href="#">HTML & CSS foundations</a></h1>
.card__title a {
color: inherit;
text-decoration: none;
}
.card__title a:hover {
color: var(--color-bg);
}
color: inherit on the anchor matters here too — browsers apply their own default link styling (blue, underlined), which would override whatever color the heading was supposed to have. Setting it back to inherit cancels that out, so the link reads as the same color as the rest of the heading until you hover it.
What changed my approach wasn't "add an anchor somewhere." It was realizing the hover target and the semantic structure needed to line up exactly — the thing that looks clickable, is clickable, exactly where it looks clickable, and nowhere else.
What both of these actually have in common
Neither one was a hard bug. Nothing crashed, nothing broke visibly in a way that demanded urgent fixing. Both were cases where something looked fine and worked almost right, and the "almost" was doing a lot of quiet work — an element not shrinking the way it should, an interaction that only half the people looking at the page would ever know existed. Small card, small build, and still two places where the obvious approach wasn't the correct one until I asked why it wasn't behaving the way I expected.
Top comments (0)