@supports selector()

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Mir war nicht bewusst, dass die Unterstützung für @supports zur Ermittlung der Selektorunterstützung so gut ist! Ich denke normalerweise an @supports als eine Möglichkeit, die Unterstützung für property: value-Paare zu testen. Aber mit der selector()-Funktion können wir auch die Unterstützung für Selektoren testen. Es sieht so aus

@supports selector(:nth-child(1 of .foo)) {

}

Du lässt den Selektor einfach zwischen die Klammern fallen und das ist es, was getestet wird.

Dieser Selektor oben ist tatsächlich ein ziemlich guter Test. Es ist ein "Selektorlisten-Argument", das für die Selektoren der :nth-child 'n'-Freunde funktioniert. Soweit ich weiß, wird er derzeit nur in Safari unterstützt.

Nehmen wir also an, deine ideale Situation ist, dass der Browser diesen Selektor unterstützt. Hier ist ein Beispiel. Du weißt, dass bei <ol> und <ul> das einzige gültige Kind-Element <li> ist. Aber sagen wir auch, dass diese Liste Trennzeichen benötigt, also hast du (und ich sage nicht, dass das eine gute Idee ist) diese Art von Ding gemacht

<ul>
  <li class="list-item">List item</li>
  <li class="list-item">List item</li>
  <li class="separator"></li>
  /* ... */
</ul>

Dann möchtest du die Liste auch im Zickzackmuster einfärben. Und wenn du Zickzackfärbung möchtest, musst du jeden zweiten .list-item auswählen und dabei die .separator ignorieren. Also…

li:nth-child(odd of .list-item) {
  background: lightgoldenrodyellow;
}

Aber nur Safari unterstützt das… also kannst du machen

@supports selector(:nth-child(1 of .foo)) {
  li:nth-child(odd of .list-item) {
    background: lightgoldenrodyellow;
  }
}

Wenn dir die Fallback-Lösung egal wäre, müsstest du dich gar nicht erst mit @supports beschäftigen. Aber sagen wir, dir ist die Fallback-Lösung wichtig. Vielleicht leistet in der unterstützten Situation die Zickzackfärbung die Hauptarbeit für das UX, das du anstrebst, sodass du für das Trennzeichen nur ein wenig Platz benötigst. Aber für nicht unterstützende Browser benötigst du etwas Robusteres, weil du keine Zickzackfärbung hast.

Jetzt kannst du also beide Situationen gestalten

@supports selector(:nth-child(1 of .foo)) {
  li {
    padding: 0.25em;
  }
  li:nth-child(odd of .list-item) {
    background: lightgoldenrodyellow;
  }
  li.separator {
    list-style: none;
    margin: 0.25em 0;
  }
}
@supports not selector(:nth-child(1 of .foo)) {
  li.separator {
    height: 1px;
    list-style: none;
    border-top: 1px dashed purple;
    margin: 0.25em 0;
  }
}

Wenn wir die @when-Syntax bekommen, können wir es etwas sauberer schreiben

/* Maybe? */
@when supports(selector(:nth-child(1 of .foo))) {

} @else {

}

Auf jeden Fall. Das Endergebnis ist…

Unterstützt
Nicht Unterstützt

Es gibt auch eine JavaScript-API zum Testen der Unterstützung. Ich war mir nicht sicher, ob das wirklich funktionieren würde, aber es scheint! Das schlägt in Chrome fehl und funktioniert in Safari, soweit ich weiß

CSS.supports("selector(:nth-child(1 of .foo))")

Während ich das hier zusammenstellte, dachte ich… hmmmmmmm — welche CSS-Selektoren gibt es mit seltsamer Cross-Browser-Unterstützung? Es sind wirklich nicht viele. Und selbst von denen, die seltsame Cross-Browser-Unterstützung haben, ist die Anzahl der Anwendungsfälle, bei denen es dir tatsächlich wichtig ist, sie in eine @supports-Anweisung zu packen (anstatt sie einfach fehlschlagen zu lassen), ziemlich gering.

Das ::marker-Pseudo-Element wäre ein gutes Beispiel gewesen, aber es wird jetzt ziemlich gut unterstützt. Ich dachte, der Fall-insensitive Attributselektor, wie [href$="pdf" i], wäre ein gutes gewesen, aber nein, auch gut unterstützt. Das Gleiche gilt für das Komma-separierte :not(a, .b, [c]). Vielleicht wäre etwas wie :fullscreen / :-webkit-full-screen interessant und nützlich, weil es einzigartig nicht in iOS Safari unterstützt wird?