[html] problem with <select> and :after with CSS in WebKit

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?

This question is related to html css select

The answer is


<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;
}

This post may help http://bavotasan.com/2011/style-select-box-using-only-css/

He is using a outside div with a class for resolving this issue.

<div class="styled-select">
  <select>
    <option>Here is the first option</option>
    <option>The second option</option>
  </select>
</div>

Faced the same problem. Probably it could be a solution:

<select id="select-1">
    <option>One</option>
    <option>Two</option>
    <option>Three</option>
</select>
<label for="select-1"></label>

#select-1 {
    ...
}

#select-1 + label:after {
    ...
}

This solution is similar to the one from sroy, but with css triangle instead of web font:

_x000D_
_x000D_
.select-wrapper {_x000D_
  position: relative;_x000D_
  width: 200px;_x000D_
}_x000D_
.select-wrapper:after {_x000D_
  content: "";_x000D_
  width: 0;_x000D_
  height: 0;_x000D_
  border-left: 5px solid transparent;_x000D_
  border-right: 5px solid transparent;_x000D_
  border-top: 6px solid #666;_x000D_
  position: absolute;_x000D_
  right: 8px;_x000D_
  top: 8px;_x000D_
  pointer-events: none;_x000D_
}_x000D_
select {_x000D_
  background: #eee;_x000D_
  border: 0 !important;_x000D_
  border-radius: 0;_x000D_
  -webkit-appearance:none;_x000D_
  -moz-appearance:none;_x000D_
  appearance:none;_x000D_
  text-indent: 0.01px;_x000D_
  text-overflow: "";_x000D_
  font-size: inherit;_x000D_
  line-height: inherit;_x000D_
  width: 100%;_x000D_
}_x000D_
select::-ms-expand {_x000D_
  display: none;_x000D_
}
_x000D_
<div class="select-wrapper">_x000D_
  <select>_x000D_
    <option value="1">option 1</option>_x000D_
    <option value="2">option 2</option>_x000D_
    <option value="3">option 3</option>_x000D_
  </select>_x000D_
</div>
_x000D_
_x000D_
_x000D_


This is a modern solution I cooked up using font-awesome. Vendor extensions have been omitted for brevity.

HTML

<fieldset>
    <label for="color">Select Color</label>
    <div class="select-wrapper">
        <select id="color">
            <option>Red</option>
            <option>Blue</option>
            <option>Yellow</option>
        </select>
        <i class="fa fa-chevron-down"></i>
    </div>
</fieldset>

SCSS

fieldset {
    .select-wrapper {
        position: relative;

        select {
            appearance: none;
            position: relative;
            z-index: 1;
            background: transparent;

            + i {
                position: absolute;
                top: 40%;
                right: 15px;
            }
        }
    }

If your select element has a defined background color, then this won't work as this snippet essentially places the Chevron icon behind the select element (to allow clicking on top of the icon to still initiate the select action).

However, you can style the select-wrapper to the same size as the select element and style its background to achieve the same effect.

Check out my CodePen for a working demo that shows this bit of code on both a dark and light themed select box using a regular label and a "placeholder" label and other cleaned up styles such as borders and widths.

P.S. This is an answer I had posted to another, duplicate question earlier this year.


I was looking for the same thing since the background of my select is the same as the arrow color. As previously mentioned, it is impossible yet to add anything using :before or :after on a select element. My solution was to create a wrapper element on which I added the following :before code.

.select-wrapper {
    position: relative;
}

.select-wrapper:before {
    content: '\f0d7';
    font-family: FontAwesome;
    color: #fff;
    display: inline-block;
    position: absolute;
    right: 20px;
    top: 15px;
    pointer-events: none;
}

And this my select

select {
    box-sizing: border-box;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    width: 100%;
    padding: 10px 20px;
    background: #000;
    color: #fff;
    border: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

select::-ms-expand {
    display: none;
}

I have used FontAwesome.io for my new arrow, but you can use whatever else you want. Obviously this is not a perfect solution, but depending on your needs it might be enough.


To my experience it simply does not work, unless you are willing to wrap your <select> in some wrapper. But what you can do instead is to use background image SVG. E.g.

    .archive .options select.opt {
    -moz-appearance: none;
    -webkit-appearance: none;
    padding-right: 1.25EM;
    appearance: none;
    position: relative;
    background-color: transparent;
    background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' height='10px' width='15px'%3E%3Ctext x='0' y='10' fill='gray'%3E%E2%96%BE%3C/text%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-size: 1.5EM 1EM;
    background-position: right center;
    background-clip: border-box;
    -moz-background-clip: border-box;
    -webkit-background-clip: border-box;
}

    .archive .options select.opt::-ms-expand {
        display: none;
    }

Just be careful with proper URL-encoding because of IE. You must use charset=utf8 (not just utf8), don't use double-quotes (") to delimit SVG attribute values, use apostrophes (') instead to simplify your life. URL-encode s (%3E). In case you havee to print any non-ASCII characters you have to obtain their UTF-8 representation (e.g. BabelMap can help you with that) and then provide that representation in URL-encoded form - e.g. for ? (U+25BE BLACK DOWN-POINTING SMALL TRIANGLE) UTF-8 representation is \xE2\x96\xBE which is %E2%96%BE when URL-encoded.


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.


Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to select

Warning: Use the 'defaultValue' or 'value' props on <select> instead of setting 'selected' on <option> SQL query to check if a name begins and ends with a vowel Angular2 *ngFor in select list, set active based on string from object SQL: Two select statements in one query How to get selected value of a dropdown menu in ReactJS DATEDIFF function in Oracle How to filter an array of objects based on values in an inner array with jq? Select unique values with 'select' function in 'dplyr' library how to set select element as readonly ('disabled' doesnt pass select value on server) Trying to use INNER JOIN and GROUP BY SQL with SUM Function, Not Working