Urgent.News

What's breaking now, across thousands of outlets.

Tech

The Dropdown You've Been Faking for a Decade

Design wants a country picker. Nothing fancy — a dropdown, a small flag icon next to each name. You reach for <select> , type the first <option> , and hit the wall every frontend dev hits eventually: an <option> can only ever show text. No <img> , no icon span, nothing. The browser renders whatever markup you put inside it as a plain string. So you do what everyone does. You build a fake one. The…

Design teams often create their own dropdown components to add icons to the options. However, the standard HTML select element has limitations — it can only display text, not images. To work around this, developers tend to build their own dropdowns using divs and buttons, resulting in custom code that's not as robust as the native select element.

One approach is to use ARIA roles and attributes, creating a role="listbox" div with role="option" children containing the actual markup. This allows for keyboard navigation and screen reader compatibility. However, positioning issues arise when the dropdown is placed inside a card component with overflow: hidden. The custom popup gets clipped by the card's edges, even though it's a child of a parent div.

The solution is to use the new CSS property `appearance: base-select;`. This tells the browser to style the custom dropdown like a native select element, including the ability to have real markup in the options. Additionally, using the `::picker(select)` pseudo-element allows the custom dropdown to be positioned above the clipping container, avoiding the overflow issue entirely.

While this custom dropdown solution requires a bit of CSS work, it eliminates the need for complex JavaScript code and provides a more accessible and maintainable solution. However, support for this feature is not universal yet, so it's recommended to use feature detection and provide fallbacks for browsers that don't support it. This way, users can still benefit from the dropdown functionality while avoiding the pitfalls of a hand-rolled component.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Vue Composables: The Shared State Trap (+ Cheat Sheet)

You build a useCounter() composable, drop <Counter /> on the page twice, and click the first button. Both counters go up. You didn't copy-paste a bug.

  • Two instances of useCounter() share same state due to JavaScript scoping rules.
  • State declared outside function is created once, shared across composable instances.
  • Confusion and unexpected behavior can arise from shared state in composables.

I built a browser extension to show pixel diffs in GitHub PRs

I've been using AI to write more code, which has also meant writing more tests—including screenshot tests to catch unexpected UI changes.

  • Software developer created gh-pixel-diff extension for GitHub PRs.
  • Extension adds pixel diff functionality within PRs without installation.
  • Users can save comparison views as PNG files for review comments.

More from Tuesday 22 September →