problema con <select> e: after con CSS in WebKit


123

Vorrei aggiungere uno stile su una casella di selezione con lo pseudo: dopo (per modellare la mia casella di selezione con 2 parti e senza immagini). Ecco l'HTML:

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

E non funziona. Non so perché e non ho trovato la risposta nelle specifiche W3C. Ecco il 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;
}

Quindi è normale o c'è un trucco?


Immagino che questo non sarebbe, non dovrebbe essere possibile, altrimenti sarebbe troppo facile cambiare il contenuto dei moduli. Immagina un semplice bit di CSS che cambia il prezzo di visualizzazione di qualcosa. Potrebbe essere mostrato come più economico di quanto non sia in realtà, inducendo le persone a comprare qualcosa per più di quanto si aspettassero. (Oppure, naturalmente, se qualcuno ha accesso al CSS di una pagina / foglio di stile utente, probabilmente potrebbe fare lo stesso in altri modi ...)
Synetech

22
@ Synetech - Questo non è corretto, l'autore della pagina dovrebbe avere il controllo completo su tutti gli aspetti dello stile della pagina. I produttori di browser che tentano di impedire lo styling di determinati elementi perché potrebbero essere utilizzati per fuorviare gli utenti non saranno efficaci in quanto esistono un numero quasi illimitato di modi per ingannare il sistema o produrre falsi positivi.
Jonathan Cross

1
Possibile duplicato di Pseudo elementi e tag SELECT
Tessa

Risposte:


132

Non l'ho verificato a fondo, ma ho l'impressione che ciò non sia (ancora?) Possibile, a causa del modo in cui gli selectelementi vengono generati dal sistema operativo su cui gira il browser, piuttosto che dal browser stesso.


62
È il 2019 adesso ed è sempre lo stesso
Placido

40
È il 2020 ora ed è sempre lo stesso
Joeri Minnekeer il

3
Se avessi visto il tuo commento su questo post di 10 anni fa un'ora fa, mi sarei risparmiato un'ora del mio tempo. : C
ericek111

66

Stavo cercando la stessa cosa poiché lo sfondo della mia selezione è lo stesso del colore della freccia. Come accennato in precedenza, è impossibile ancora aggiungere qualcosa usando: before o: after su un elemento select. La mia soluzione era creare un elemento wrapper su cui ho aggiunto quanto segue: 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;
}

E questa è la mia scelta

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

Ho usato FontAwesome.io per la mia nuova freccia, ma puoi usare qualsiasi altra cosa tu voglia. Ovviamente questa non è una soluzione perfetta, ma a seconda delle tue esigenze potrebbe essere sufficiente.


4
Questo è visivamente perfetto. Ma non puoi fare clic su quell'icona e selezionare l'elemento non si aprirà: / Eventuali suggerimenti?
Schovi

11
eventi-puntatore: nessuno; dovrebbe occuparsene. Si è verificato un problema con il mio codice sopra. Cambierò qualsiasi sass sopra in css per rimuovere qualsiasi confusione.
sroy

È importante quale pseudo selettore (prima o dopo) viene utilizzato?
eddiegroves

Puoi usare l'uno o l'altro
sroy

2
Questa è un'ottima soluzione, ma durante l'implementazione ho scoperto che per qualche motivo: prima funzionava e NON: dopo. Non so perché
Lee Probert

32

Per la mia esperienza semplicemente non funziona, a meno che tu non sia disposto a avvolgerlo <select>in qualche involucro. Ma quello che puoi fare invece è usare l'immagine di sfondo SVG. Per esempio

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

Basta fare attenzione con la corretta codifica URL a causa di IE. Devi usare charset=utf8(non solo utf8), non usare virgolette doppie (") per delimitare i valori degli attributi SVG, usa invece gli apostrofi (') per semplificarti la vita. URL-encode s (% 3E). Nel caso tu debba stampare qualsiasi carattere non ASCII necessario per ottenere la loro rappresentazione UTF-8 (ad es. BabelMap può aiutarti in questo) e quindi fornire quella rappresentazione in forma codificata URL - ad es. per ▾ ( U+25BETRIANGOLO NERO CON PUNTAMENTO GIÙ) La rappresentazione UTF-8 è \xE2\x96\xBEche è %E2%96%BEquando codificato in URL.


1
Questa è una soluzione carina ed elegante
JosFabre

1
Questa è una soluzione fantastica, semplice ed elegante che non richiede HTML extra, che è esattamente quello che stavo cercando! Grazie! Questa dovrebbe essere la risposta scelta IMO.
KyleFarris


13

Ha affrontato lo stesso problema. Probabilmente potrebbe essere una soluzione:

<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 {
    ...
}

Puoi aggiungere gli stili necessari per far sì che l'etichetta si trovi sopra l'elemento selezionato?
bafromca

7

Questa soluzione è simile a quella di sroy, ma con triangolo CSS invece del carattere web:

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


6

E se la modifica del markup non fosse un'opzione?

Ecco una soluzione che non ha requisiti per un wrapper: utilizza un SVG in un'immagine di sfondo. Potrebbe essere necessario utilizzare un decodificatore di entità HTML per capire come modificare il colore di riempimento.

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

Pizzicato da CSS-Tricks .


Questo è un bel trucco. Super fastidioso che non possiamo ancora selezionare lo stile nel 2020.
ramijames

5

Questa è una soluzione moderna che ho inventato usando font-awesome . Le estensioni dei fornitori sono state omesse per brevità.

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

Se l'elemento di selezione ha un colore di sfondo definito, questo non funzionerà poiché questo frammento essenzialmente posiziona l'icona Chevron dietro l'elemento di selezione (per consentire di fare clic sulla parte superiore dell'icona per avviare comunque l'azione di selezione).

Tuttavia, puoi applicare uno stile al wrapper di selezione alla stessa dimensione dell'elemento di selezione e modellare lo sfondo per ottenere lo stesso effetto.

Controlla il mio CodePen per una demo funzionante che mostra questo bit di codice su una casella di selezione a tema sia scuro che chiaro utilizzando un'etichetta normale e un'etichetta "segnaposto" e altri stili puliti come bordi e larghezze.

PS Questa è una risposta che avevo postato a un'altra domanda duplicata all'inizio di quest'anno.


1
<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 don't you add a div out-side the select.

e stile quindi 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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.