Better Icon and Label Alignment 🔥 Build any web layout, with confidence. Checkout The Layout Maestro course. Learn more Ahmad Shadeed , Design Engineer Home Course Articles Work About Speaking Contact Switch to dark Better Icon and Label AlignmentSep 15, 2026 Table of contents The icon in the markup The solution: using the lh unit Icon as a pseudo-element The solution Outro The Layout Maestro There is a common design pattern that sometimes gets missed or overlooked. It’s having a list of items, each with an icon. When the text is one line, the icon is centered, but when the text has multiple lines, the icon is still centered but looks odd. Here is an example: Throughout this article, I will show two solutions that I use based on the HTML:
The icon is an HTML element (e.g., <svg> or <img>) The icon is added via a pseudo-element as a background image
The icon in the markup In this case, we have a container with the icon and the content. Usually, we use flexbox. Like so: <ul class="list"> <li class="list-item"> <svg class="icon"></svg> <span class="label">How to align an icon to a label.</span> </li> <!-- Other items --> </ul>
.list-item { display: flex; align-items: center; gap: 0.5rem; }
By default, it looks okay. Here it is: List385pxHighlightHow to align an icon to a label. However, when the list width is smaller and the text wraps, the icon will be centered. This is not the behavior we want. List250pxHighlightHow to align an icon to a label. How can we keep the icon aligned vertically when the text is wrapped? First, I went back to the basics. Instead of using align-items: center, I used start as a value. .list-item { display: flex; align-items: start; gap: 0.5rem; }
But this caused an even bigger alignment issue. The highlighted area is the line height. The text element height has an empty space above and below it that comes from the font itself. When align-items: start is applied, the icon will be aligned to the top of the container. List250pxHighlightHow to align an icon to a label. What if we pushed the icon down to have it aligned with the top line? List250pxHighlightHow to align an icon to a label. .list-item { display: flex; align-items: start; gap: 0.5rem; }
.icon { transform: translateY(3px); }
That works. Let’s push the limits of it and see if it persists! To do that, I built the demo in a way that changes one or more of the following:
List item font size Icon size List container width
Try it and notice how the icon becomes misaligned. Icon20pxFont size25pxList250pxHighlightHow to align an icon to a label. Using a fixed value for the transform won’t work when the icon size, font size, or container width changes. The solution: using the lh unit If we can get the line-height value and we have a known icon size, we can make the offset relative to them. I wrote about the line height unit on the blog if you want to dig further. .icon { /* --icon-size is defined via JS. */ --size: var(--icon-size); --offset: calc((1lh - var(--size)) / 2); transform: translateY(var(--offset)); }
Icon20pxFont size25pxList250pxHighlightHow to align an icon to a label. In this solution, if you change any of the three values, the alignment will just work. In some cases, the offset might be negative, just like the following example: Icon24pxFont size17pxList250pxHighlightHow to align an icon to a label. Icon as a pseudo-element Sometimes, we don’t need to add the icon as an HTML element, so we use a pseudo-element for that. Here is the basic CSS: .list-item { display: flex; gap: 0.5rem; }
.list-item::before { content: ""; --size: var(--icon-size); width: var(--size); height: var(--size); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23222' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E"); background-repeat: no-repeat; }
At first glance, it looks fine, right? Try to increase the font size a bit. Icon24pxFont size17pxList264pxHighlightHow to align an icon to a label. Did you notice that the icon is cut off? This is because we need to limit the background size. .list-item { display: flex; gap: 0.5rem; }
.list-item::before { content: ""; --size: var(--icon-size); width: var(--size); height: var(--size); background-image: url("data:image/svg+xml,%3Csvg ...."); background-size: contain; background-repeat: no-repeat; } Icon24pxFont size17pxList264pxHighlightHow to align an icon to a label. Try to make the font size larger. Did you notice that the icon width shrinks? This is because, by default, a flex item will shrink. We need to override that. .list-item { display: flex; gap: 0.5rem; }
.list-item::before { content: ""; --size: var(--icon-size); flex-shrink: 0; width: var(--size); height: var(--size); background-image: url("data:image/svg+xml,%3Csvg ...."); background-size: contain; background-repeat: no-repeat; } Icon24pxFont size17pxList264pxHighlightHow to align an icon to a label. Again… try to increase the font size of the label. The icon size stays as is. The next step is to handle centering while factors like icon size, font size, and container width change. The solution Currently, the list item is a flexbox container, and by default, the items stretch (vertically). Why isn’t the icon stretching in our case? Well, this is because we set a fixed height. I set the height property to auto. .list-item { display: flex; gap: 0.5rem; }
.list-item::before { content: ""; --size: var(--icon-size); flex-shrink: 0; width: var(--size); height: auto; background-image: url("data:image/svg+xml,%3Csvg ...."); background-size: contain; background-repeat: no-repeat; } Icon24pxFont size17pxList264pxHighlightHow to align an icon to a label. Now it’s a bit trickier. If you increase the font size, the icon width will stay square-like. If you decrease it, it will become rectangle-like with extra spacing. Take a look: Icon24pxFont size14pxList264pxHighlightHow to align an icon to a label. To avoid that, we need to force the aspect ratio to a square. .list-item { display: flex; gap: 0.5rem; }
.list-item::before { content: ""; --size: var(--icon-size); flex-shrink: 0; aspect-ratio: 1; width: var(--size); height: auto; background-image: url("data:image/svg+xml,%3Csvg ...."); background-size: contain; background-repeat: no-repeat; } Icon24pxFont size14pxList264pxHighlightHow to align an icon to a label. With that, we will use the same technique as before and offset the pseudo-element by a few pixels. .list-item { display: flex; gap: 0.5rem; }
.list-item::before { content: ""; --size: var(--icon-size); --offset: calc((1lh - var(--size)) / 2); flex-shrink: 0; aspect-ratio: 1; width: var(--size); height: auto; background-image: url("data:image/svg+xml,%3Csvg ...."); background-size: contain; background-repeat: no-repeat; transform: translateY(var(--offset)); } Icon24pxFont size14pxList264pxHighlightHow to align an icon to a label. The icon is now centered. It’s interesting to see what’s been used here:
flexbox aspect-ratio the lh unit calc() height: auto
Outro And that’s it. I solved a problem while working on a project and wanted to share it. Hope you’ve learned something new. Thanks for reading. The Layout Maestro Building layouts can be a challenging task, especially if you don’t know the core mental model of CSS layouts. You don’t have to worry about that anymore. I released an interactive CSS layout course, and I called it The Layout Maestro. Check out The Layout Maestro course and level up your CSS layout skills. Join my mailing list Join over 3400+ subscribers to explore my thoughts and favorite links from around the web. I will share content that: Clear and explain the point without too much words. Contains at least one figure or clear example. Make you learn something new, or at least to remind you of it. Rest assure that you will receive top notch quality content recommendations. Your email That's the end of Ahmad Shadeed's website. Home Articles Work Services About Speaking Contact Find me online BlueSky X Matsodon Codepen Github Threads Instagram RSS feed 👋 Come and say hello [email protected] & Let's grab a coffee |
The article addresses a common design pattern challenge in web layout: achieving proper alignment between icons and their corresponding labels, particularly when the label text spans multiple lines within a list item. The initial issue arises because standard flexbox centering, such as using align-items: center, results in the icon being centered relative to the label block, which appears visually incorrect when the text wraps, as the desired vertical alignment is lost.
The author explores two primary methods for implementing icons: using an actual HTML element, such as SVG or image, or using a pseudo-element as a background image. When using HTML elements, the initial attempt to adjust alignment using flexbox failed because changing the alignment property impacted the surrounding elements' height, leading to further misalignment. An iterative approach was taken, involving applying a manual vertical translation via transform to correct the vertical positioning, but this solution proved unstable, failing when related factors like font size, icon size, or container width were modified.
A more robust solution was introduced by leveraging the line-height unit (lh) to create a relative offset. This technique allows the vertical offset adjustment to be calculated dynamically based on the line height and the icon size, enabling the icon to be precisely centered regardless of changes in font size or container dimensions.
Subsequently, the approach shifted to using pseudo-elements for the icon, which introduced new complexities related to ensuring the icon maintained a square aspect ratio and managed its size correctly within the flex container. To address alignment issues when font sizes varied, the method incorporated the aspect-ratio property to enforce a square shape for the icon element. This was combined with the line-height based offset calculation and a final transform to achieve the desired centered alignment reliably, accommodating variable dimensions.
The final, refined solution integrates several advanced CSS concepts, including flexbox for the container, aspect-ratio to manage the icon's shape, the line-height unit for precise spacing calculations, and the transform property for fine-tuning the vertical placement. This combination allows the layout to remain correctly aligned even when variable inputs like font size and overall container width are adjusted. The core techniques employed include flexbox, aspect-ratio, the lh unit, calc(), and height: auto to manage the dynamic spatial relationships between the icon and the label. |