DEV Community

James
James

Posted on • Edited on

Select dropdown arrow styling with Emotion

I'm a big fan of keeping UI controls simple, preferably without the need for client-side javascript. Thankfully CSS has progressed (❤️ appearance: none;) to the point where we can style form controls well enough for most UX & brand guidelines.

Here's a technique with Emotion that uses an SVG background-image and CSS Custom Properties to style the Select's dropdown arrow. It's pretty simple and works client-side using CSS alone.

const makeGlyph = (colour: string, alpha = '100%') =>
  encodeURIComponent(`<svg ...><path ... fill="hsla(${colour}, ${alpha})"/></svg>`);

export const Select = styled.select`
  ${({ theme }) => {
    const enabledGlyph = makeGlyph(theme.colour.neutral);
    const disabledGlyph = makeGlyph(theme.colour.neutral, '50%');
    const activeGlyph = makeGlyph(theme.colour.primary);
    const prefix = `data:image/svg+xml;charset=utf-8`;

    return css`
      --primary: url('${prefix},${enabledGlyph}');
      --disabled: url('${prefix},${disabledGlyph}');
      --active: url('${prefix},${activeGlyph}');
    `;
  }};

  ${otherSelectStyles}

  --glyph: var(--primary);

  appearance: none;
  background: no-repeat right center / 1em;

  &:not([multiple]):not([size]) {
    background-image: var(--glyph);
    transition: background-image 0.2s;
  }

  &:disabled {
    --glyph: var(--disabled);
  }

  &:not(:disabled) {
    &:hover,
    &:focus {
      --glyph: var(--active);
    }
  }
`;
Enter fullscreen mode Exit fullscreen mode

Top comments (0)