problem with <select> and :after with CSS in WebKit

Viewed 211278

I would like to add some style on a select box with the pseudo :after (to style my select box with 2 parts and without images). Here's the HTML:

<select name="">
  <option value="">Test</option>
</select>

And it doesn't work. I don't know why and I didn't find the answer in the W3C specs. Here's the CSS:

select {
  -webkit-appearance: none;
  background: black;
  border: none;
  border-radius: 0;
  color: white;
}

select:after {
  content: " ";
  display: inline-block;
  width: 24px; height: 24px;
  background: blue;
}

So is it normal or is there a trick?

11 Answers

What if modifying the markup isn't an option?

Here's a solution that has no requirements for a wrapper: it uses an SVG in a background-image. You may need to use an HTML entity decoder to understand how to change the fill colour.

-moz-appearance: none;
-webkit-appearance: none;
appearance: none;

background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23000000%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
background-repeat: no-repeat;
background-position: right .7em top 50%;
background-size: .65em auto;

Pinched from CSS-Tricks.

<div class="select">
<select name="you_are" id="dropdown" class="selection">
<option value="0" disabled selected>Select</option>
<option value="1">Student</option>
<option value="2">Full-time Job</option>
<option value="2">Part-time Job</option>
<option value="3">Job-Seeker</option>
<option value="4">Nothing Yet</option>
</select>
</div>

Insted of styling the select why dont you add a div out-side the select.

and style then in CSS

.select{
    width: 100%;
    height: 45px;
    position: relative;
}
.select::after{
    content: '\f0d7';
    position: absolute;
    top: 0px;
    right: 10px;
    font-family: 'Font Awesome 5 Free';
    font-weight: 900;
    color: #0b660b;
    font-size: 45px;
    z-index: 2;

}
#dropdown{
    -webkit-appearance: button;
       -moz-appearance: button;
            appearance: button;
            height: 45px;
            width: 100%;
        outline: none;
        border: none;
        border-bottom: 2px solid #0b660b;
        font-size: 20px;
        background-color: #0b660b23;
        box-sizing: border-box;
        padding-left: 10px;
        padding-right: 10px;
}

Instead of a wrapper element you can use CSS grid and place an icon (or whatever) in the same cell as the select:

.select-field {
  display: grid;
  grid-template:
    "label"
    "select"
    / max-content;
}

.label {
  grid-area: label;
}

.select {
  appearance: none;
  background: white;
  border: 1px solid var(--border-color);
  grid-area: select;
  padding-block: 0.5ex;
  padding-inline: 1ch calc(1ch + 1em);
}

.after {
  align-self: center;
  border-block-start: 0.5em solid var(--border-color);
  border-inline: 0.5em solid transparent;
  block-size: 0;
  grid-area: select;
  inline-size: 0;
  justify-self: end;
  margin-inline-end: 1ch;
  pointer-events: none;
}

.select,
.select + .after {
  --border-color: silver;
}

.select:hover,
.select:hover + .after {
  --border-color: grey;
}

.select:focus,
.select:focus + .after {
  --border-color: rebeccapurple;
}
<div class="select-field">
  <label for="my-select" class="label">Select One</label>

  <select id="my-select" class="select">
    <option value="foo">Foo</option>
    <option value="bar">Bar</option>
    <option value="baz">Baz</option>
  </select>
  
  <div class="after"></div>
</div>

Here I used an empty div to and styled it to be a CSS triangle which has the same color as the border which changes during hover/focus.

The most important bits here are the following:

  • The <select> and the <div class="after"> go into the same grid-area (which I named select). This will put the empty div over the select.
  • Give the <select> an appearance of none. This will remove any browser default style.
  • Give the <select> and extra padding at the end of the inline direction to make room for the empty style.
  • Justify the empty div to the end.
  • Give the empty div an extra margin at the end of the inline direction which matches your desired padding of the <select>
  • Give the empty div a pointer-events of none so the click will go through it to the <select> element.

Other then that you can do whatever with the empty div. It doesn’t even have to be empty. E.g. you can put an svg icon in there if you want.

If you chose to use the select::after method, remember that:

.select::after{
       ...
       pointer-events: none;
       ...

for clickable..

Related