Ich bin ein großer Fan davon, box-sizing auf border-box zurückzusetzen, so sehr, dass wir einen besonderen Tag im Jahr dafür haben. Aber es gibt eine kleine Anpassung beim Setzen, die eine ziemlich gute Idee zu sein scheint.
Hier ist die angepasste Version
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
Die Idee der Vererbung verdanke ich Jon Neal hier, der sagt
Das gibt Ihnen das gleiche Ergebnis und erleichtert die Änderung des box-sizing in Plugins oder anderen Komponenten, die ein anderes Verhalten nutzen.
Um das weiter zu erklären: Nehmen wir an, Sie haben eine Komponente, die nur für die Arbeit mit dem Standard-content-box box-sizing entwickelt wurde. Sie möchten sie einfach nur verwenden und nicht daran herumfummeln.
.component {
/* designed to work in default box-sizing */
/* in your page, you could reset it to normal */
box-sizing: content-box;
}
Das Problem ist, dass dies nicht die gesamte Komponente zurücksetzt. Vielleicht gibt es ein <header> innerhalb dieser Komponente, das in einer content-box-Welt erwartet wird. Wenn dieser Selektor in Ihrem CSS vorhanden ist, in der "alten Methode", ein box-sizing-Reset durchzuführen...
/* This selector is in most "old way" box-sizing resets */
* {
box-sizing: border-box;
}
Dann ist dieser Header nicht content-box, wie Sie vielleicht erwarten, sondern border-box. Wie
<div class="component"> <!-- I'm content-box -->
<header> <!-- I'm border-box still -->
</header>
</div>
Um diesen Reset einfacher und intuitiver zu gestalten, können Sie den oben gezeigten Vererbungs-Snippet verwenden, und die Vererbung wird beibehalten.
Es funktioniert
Siehe den Pen Easy to Reset Box-Sizing von Chris Coyier (@chriscoyier) auf CodePen.
Das ist keine große Sache. Vielleicht verwenden Sie bereits den "alten" box-sizing-Reset und sind nie damit in Schwierigkeiten geraten. Das ist bei mir der Fall. Aber da wir ein "Best-Practice"-Snippet fördern, können wir es auch so gut wie möglich gestalten.
Meiner Meinung nach gibt es eine Situation, in der border-box standardmäßig nicht erwünscht ist: img.
Versuchen Sie, einem Bild einen Rahmen mit "box-sizing: border-box" zu geben. Das Bild wird in der Größe verändert.
Ich füge normalerweise die Pseudoklasse :not() für Bilder hinzu
Sie könnten
imgs direkt mit box-sizing: content-box ansprechen, anstatt den potenziell teuren:not-Selektor zu verwenden@sanson, ich bin neugierig. Wie kann ein Bild verkleinert werden, wenn der Rahmen außen erzeugt wird?
In diesem Pen können Sie deutlich sehen, dass beide Bilder die gleichen Abmessungen haben, auch wenn eines davon einen 10-Pixel-Rahmen hat: http://codepen.io/ricardozea/pen/anCyq
Fehlt mir da etwas?
Könnten Sie bitte eine Demo erstellen, in der wir sehen können, was Sie sagen?
Danke im Voraus,
@sanson, wenn Sie *responsive* Bilder verwenden, die Sie einfach auf
width:100%ihres Containers setzen möchten, dann *möchten* Sie höchstwahrscheinlichborder-box... siehe diese modifizierte Version von Ricardos Codepen, http://codepen.io/anon/pen/sijtD – ohneborder-box"bricht" das Bild mit dem Rahmen aus seinem enthaltenden Element aus, was höchstwahrscheinlich nicht das ist, was Sie unter diesen Umständen wollen würden.@sanson hat Recht.
Bild wird in der Größe verändert: http://codepen.io/ricardozea/pen/KtFlH (Ich habe die Rahmenbreite erhöht, um dieses Problem besser zu sehen).
In der neuen Demo habe ich
html { box-sizing: border-box; }zu* { box-sizing: border-box; }geändert) und zack! Das Bild wird in der Größe verändert.Das ist jedoch das gewünschte Ergebnis, wenn Sie mich fragen.
Wenn Sie
:not(img)zum universellen Selektor hinzufügen [*:not(img) { box-sizing: border-box; }], dann sehen Sie, dass das Bild die gleiche Größe behält und aus seinem Container "herausragt".Das rettet Leben. Ernsthaft
Ich liebe die Idee,
:not-Selektoren zu verwenden. So sehr, dass jede Komponente, die ich baue, mit einem:not(.exclude)gestylt wird.Macht es sehr einfach, jede Funktionalität zu überschreiben, ohne Schritte zurückverfolgen zu müssen.
Ich habe dies kürzlich auf einer Website getan, bei der alle Schaltflächen beim Klicken animiert werden. Als ich dieselbe Komponente in einer Schaltflächengruppe verwendete, verursachte dies Probleme.
Hier gewinnt box-shadow über border.
Dafür habe ich tatsächlich einen Sass-Mixin erstellt: http://codepen.io/ricardozea/pen/5d729855e63d404f0dfa46bda3bb56d1/
Ehrlich gesagt, dieser Mixin verwendet den
inset-Wert. Wenn Sie ihn also für Bilder verwenden möchten, entfernen Sie deninset-Wert aus derbox-shadow-Deklaration und voilà, der Rahmen ist jetzt außen.Am Ende des Artikels ein Bonuspünkt für die Verwendung von "gotten" statt "got", aber es sollte "never been bitten" heißen.
Könnte man nicht einfach verwenden
Absolut, das könnten Sie. Sie müssen nur daran denken, es zu tun, da es nicht sehr intuitiv ist (zumindest für mich). Und es ist ein Fall von "etwas tun, nur um es wieder rückgängig zu machen". Keine große Sache, aber wie ich am Ende des Artikels sagte, wenn wir dieses "Best-Practice"-Snippet teilen, können wir es auch so gut wie möglich gestalten.
Ich stimme zu, es scheint genauso einfach und insgesamt kürzer, es auf diese Weise zu tun. Es sei denn, inherit hat irgendeinen Leistungsvorteil gegenüber dem Setzen jedes Elements, was ich mir nicht vorstellen kann, dann scheint dies intuitiver und offensichtlicher.
Obwohl in seinem spezifischen Beispiel, zur Vollständigkeit, das CSS sein müsste
Der Artikel erweckt den Eindruck, dass es schwierig ist, eine bestimmte Teilmenge des HTML auf content-box zurückzusetzen, aber die Realität ist, dass es einfach ist.
Richtig, aber warum überhaupt darüber nachdenken, wenn man einfach die Komponente zurücksetzen und das war's? Alle gleichen Vorteile, einfachere Resets, kein Zurückrudern, eine leicht bessere Best Practice.
Nachdem ich erkannt habe, dass der * Selektor :before und :after nicht einschließt, würde ich Ihnen zustimmen, Chris, denn jetzt müsste der Code lauten:
um sicherzustellen, dass Sie alle Elemente innerhalb der Komponente abgedeckt haben. Und wenn Sie spezielle Regeln hätten, wie Sanson erwähnt hat, müssten Sie diese möglicherweise ebenfalls unter der aktuellen Standardmethode zurücksetzen.
Danke dafür, es klingt nach etwas, das ich in meiner Arbeit implementieren sollte.
Christian Longe, Sie vergessen auch die Pseudo-Elemente von
.component.Eine etwas abwegige Frage
@Christian Longe (nun ja, eigentlich alle anderen auch): Wie kommt es, dass der
*-Selektor:beforeund:afternicht einschließt?* {}ist wiehtml {}, es ist ein universeller Selektor für den Namen des Elements. So wie es*:hover(Pseudoklasse) gibt, gibt es*::before(Pseudo-Element).Ich denke,
.component *ist schlecht in Bezug auf die Selektorleistung, während*und.componentviel besser sind.@PhistucK, da muss ich widersprechen,
html {}ist kein universeller Selektor, wie Sie ihn anscheinend meinen. Wie Sie lesen können, gibt es keine Verweise aufhtmlals "universell": https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors*undhtmlsind zwei völlig unterschiedliche Selektoren. Aber darum geht es bei meiner Frage nicht.Lassen Sie mich meine Frage noch einmal formulieren.
Beinhaltet der universelle Selektor
*auch die Pseudo-Elemente:beforeund:after?Sie haben mich entweder missverstanden oder ich war einfach unklar. Ich meinte, dass es wie
htmlist, da beide Elementnamen abgleichen.*ist ein universeller Selektor (bedeutet "jedes") für Elementnamen, nicht für alles und jedes in CSS.Es als "universell" zu bezeichnen, ist eigentlich ein ziemlich seltsamer Begriff. Es bedeutet wirklich "jeder Elementname".
Hier ist eine Frage –
Warum matcht
*, *:*, *::*kein Element, Pseudo-Element und keine Pseudoklasse?(Die technische Antwort ist wahrscheinlich, weil es schrecklich in Bezug auf Leistung und Speicher wäre, die konzeptionelle Antwort ist wahrscheinlich, weil es nicht sehr nützlich ist, da Browser neue Pseudo-Elemente und Pseudoklassen hinzufügen können, die plötzlich dort auftauchen können, wo sie nicht sollten, und die Standardantwort ist, dass es nicht so in den Standards spezifiziert wurde. Aber keine wirkliche Antwort)
@Ricardo Der
*-Selektor matcht nur Elemente.::beforeund::afterPseudo-Elemente sind keine richtigen Elemente (sie existieren nicht im DOM als unabhängige Elemente). Und die anderen Pseudo-Elemente (::first-line,::first-letter) müssen nicht von*gematcht werden, da sie bereits über ihr Elternelement gematcht werden. Eine Ausnahme wäre::selection, aber jetzt kommen wir nur noch zu seltsamen Grenzfällen in der Spezifikation. (Und die einzigen Eigenschaften, die für selection, first-line und first-letter gelten, sind sowieso die schriftbezogenen Eigenschaften.)Großartige Idee!
Sollte die Deklaration
html { box-sizing: border-box; }nicht nach dem Wildcard-Selektor*kommen, damit derbox-sizing-Wert korrekt kaskadiert, oder isthtmlnicht im*-Selektor enthalten? Wie folgthtml ist in * enthalten, aber die Reihenfolge spielt hier keine Rolle, es funktioniert in beide Richtungen.
Die Reihenfolge spielt keine Rolle. Der universelle Selektor (*) hat eine Spezifität von 0-0-0 und der Elementselektor
htmlhat eine höhere Spezifität von 0-0-1. Daher wird der Elementselektor unabhängig von der Quellreihenfolge gewinnen.Wenn box-sizing vererbt wird, warum müssen wir dann überhaupt inherit deklarieren? Sollte
html { box-sizing: border-box; }nicht ausreichen?Es wird nicht von Natur aus vererbt, es unterstützt nur einen inhärenten Wert, der es erzwingen kann, dass es vererbt wird.
Ha. Ich wollte vorschlagen, dass der Artikel geändert wird, um nicht zu sagen, dass box-sizing eine vererbbare Eigenschaft ist. Aber es scheint, dass Sie das bereits getan haben. ;-)
Das klärt mein Problem, da
inheritauf jede CSS-Eigenschaft angewendet werden kann, unabhängig davon, ob sie vererbbar ist oder nicht.Wo wir gerade dabei sind, was ist mit diesen *:before und after Selektoren? Wie notwendig sind sie?
Wenn Sie
:beforeund:afterverwenden undbox-sizing: border-boxmit dieser Methode anwenden möchten, müssen Sie sie so auswählen. Wenn nicht, lassen Sie sie einfach weg.Mann, ich musste ehrlich gesagt nie wieder zu
box-sizing: content-box;zurückkehren, nachdem ichborder-boxgelernt hatte.Das sieht nach einem guten Vorschlag aus. Vielleicht alle Beiträge zu diesem Thema aktualisieren (den Border Box Day Beitrag, zum Beispiel und jeden anderen Beitrag, der ein ähnliches Snippet verwendet)?
Hallo, danke für den Tipp. Inherit box size wäre ein besserer und praktischer Weg zur Größenbestimmung.
Ich glaube nicht, dass ich dieser Idee zustimme.
Wenn Sie eine spezifische Standard-Box-Sizing-Methode erstellen, wissen Sie *genau*, was Sie weiter unten erwarten können. Es ist *vorhersehbar* und hindert Sie nicht daran, eine Komponente zu erstellen, die auf eine Box-Sizing-Methode ausgerichtet ist, die sich von der Standardeinstellung unterscheidet, wenn Sie sie benötigen.
Eine Standard-Box-Sizing-Methode, die überall gleich ist, zwingt Sie möglicherweise dazu, explizit zu sein, wenn Sie eine andere Eigenschaft verwenden möchten, aber das ist in Ordnung: Explizit zu sein ist sowieso eine *gute Sache*!
Wenn Sie die Box-Sizing-Methode standardmäßig vererben, bedeutet dies, dass, sobald Sie das Verhalten eines Elements ändern, *alle verschachtelten Elemente sich plötzlich anders verhalten*, obwohl sie sich selbst *nicht* geändert haben. Das ist *unvorhersehbar*, und das macht es schwieriger zu verstehen, was passiert, wenn (und wenn) etwas schiefgeht.
Die durch unvorhersehbares Box-Sizing eingeführten Probleme verschlimmern sich, wenn Sie beginnen, Komponenten an mehreren Stellen zu verschachteln, oder wenn Sie in Zukunft Komponenten aktualisieren oder hinzufügen, oder wenn Sie in Teams arbeiten, in denen mehrere Personen denselben CSS-Code durchsuchen müssen, usw. usw.
Wenn Ihr Plugin nur mit einer Box-Sizing-Methodik funktioniert, haben Sie zwei Möglichkeiten: Das Plugin reparieren oder das CSS reparieren. Wählen Sie das, was am sinnvollsten ist, und erledigen Sie es.
Ich muss zustimmen
Chris' (ich weiß noch nicht, ob dies eine branchenübliche Vorgehensweise ist) Vorschlag ist sicherlich clever und ergibt unter sehr spezifischen Anwendungsfällen Sinn, aber je mehr ich darüber nachdenke, desto mehr befürchte ich, dass er unter dem ähnlichen Kaskadierungsproblem leiden könnte, das bei
ems auftritt.Hmm, ich bin mir nicht sicher, ob das besser ist. Nur weil man ein Element auf content-box setzen möchte, heißt das nicht, dass alles darin es auch nutzen soll. Ich glaube nicht, dass ich content-box verwenden würde, weil ich möchte, dass alle Elemente in einer "content-box-Welt" leben. Ich glaube, ich würde es für einen spezifischen Layout-Grund für dieses eine Element verwenden. Aber andererseits kann ich nicht sagen, dass ich viel Grund hatte, zu content-box zurückzukehren, also kann ich es nicht sicher sagen.
total verrückt. gut gemacht Chris/Jon
Das ist eine OO-Lösung, eine bessere Praxis. Cool Mann!
Diese Idee wird den Inhalt nicht zerstören, der das Standard-Boxmodell für alle Elemente erwartet (sofern er in einem Element mit explizit auf
content-boxgesetzterbox-sizing-Eigenschaft gekapselt ist), aber sie wird immer noch das Layout von Inhalten zerstören, die ein nicht standardmäßigesbox-sizingfür einige äußere Elemente verwenden und erwarten, dass ihre inneren Elementebox-sizingaufcontent-boxgesetzt haben (der Standardwert in CSS3 istcontent-box– nichtinherit).Ich habe Layouts gesehen, die
border-boxnur für äußere Layout-Divs verwenden, aber nicht für innere Elemente, wodurch diese das Standard-Boxmodell behalten – so müssen jetzt die inneren Elemente explizit auf einen Wert gesetzt werden, der normalerweise standardmäßig nach CSS-Standard ist. Ich spreche von der Einbeziehung von Inhalten, über die ich keine Kontrolle habe, was manchmal unvermeidlich ist.Außerdem gibt es einige Probleme mit Bildern mit Rahmen usw., so dass dort auch einige Ausnahmen benötigt werden.
Ich habe einen Vorschlag verfasst, um diese und ähnliche Probleme hoffentlich zu lösen, ohne dass Wildcard-Selektor-Hacks, Pseudoklassen oder das Hinzufügen von Klassen zu Elementen überhaupt erforderlich sind, oder das Erzwingen von Eigenschaften zur Vererbung, wenn sie im CSS-Standard nicht vorhanden sind usw. Hier ist mein Vorschlag, nur ein erster Entwurf
Besseres Box-Modell == Kein Box-Modell
https://gist.github.com/rsp/9f47e0105e105dae6869
Ich warte auf Kommentare.
Ohne Beleidigung, aber dieser Vorschlag klingt für mich etwas lächerlich...
Sie schlagen vor, die Eigenschaften
widthundheightin *acht* neue Eigenschaften aufzuteilen –width-content,width-padding,width-border,width-marginund entsprechend fürheight... glauben Sie wirklich, dass dies die Angabe von Layout-Dimensionen im wirklichen Leben erleichtern würde? Ich bezweifle das – sehr.(Außerdem macht
width-marginIMHO am wenigsten Sinn – die Einbeziehung der Ränder in die Breite oder Höhe wurde noch nie in *irgendeinem* Box-Modell gemacht, und welchen genauen Vorteil hätte das? Ich kann keine tatsächlichen Anwendungsfälle dafür finden, wo das Sinn ergeben würde. Und denken Sie daran, Ränder erlauben *negative* Werte – also würde mit Ihrem Vorschlagwidth-margin: 500pxkombiniert mitmargin: -100pxzu einem Element führen, das 700px breit ist oder was ...?)Ihre *Absicht*, die Dinge zu vereinfachen, ist in Ordnung – aber ich denke nicht, dass Sie das mit diesem Vorschlag erreichen; im Gegenteil, er fügt sogar Komplexität hinzu.
CBroe, danke für Ihren Kommentar. Der Punkt ist, dass Sie nicht alle Werte verwenden müssen und es nicht so ist, dass Breite und Höhe in andere Werte aufgeteilt werden – sie sind immer noch verfügbar, aber Sie haben auch andere Werte, die der Browser bereits kennen muss, aber jetzt haben Sie einfachen Zugriff darauf – wenn Sie sie brauchen. Zum Beispiel, anstatt zu schreiben
.x { box-sizing: border-box; width: 100px; }
können Sie verwenden
.x { width-border: 100px; }
anstatt zu schreiben
.y { box-sizing: content-box; width: 100px; }
können Sie verwenden
.y { width-content: 100px; }
Sie könnten auch verwenden
.z { width-content: 200px; height-border: 100px; }
was mit 'width' und box-sizing unmöglich ist.
Die *-margin-Werte wurden der Vollständigkeit halber hinzugefügt und sind wahrscheinlich die am wenigsten nützlichen, aber es schadet nicht, sie zu haben – Sie müssen sie nur nicht verwenden. Und ja, bei negativen Margin-Werten wäre width-margin größer als width-border. Und bevor Sie fragen – ja, bestimmte Werte wären unsinnig, wenn sie zu einer negativen Inhaltsbreite führen würden.
Ich möchte hier nicht vom Thema abweichen, aber ich werde gerne alle Kommentare auf GitHub und Twitter beantworten.
https://gist.github.com/rsp/9f47e0105e105dae6869
Wenn dies ein Best-Practice-Snippet ist, dachte ich, ich könnte es leicht im Snippets-Bereich finden. Vielleicht suche ich einfach nicht richtig, aber ich konnte es nicht finden. Sage es nur :)
Nur zur Info, ich schätze, Sie brauchen immer noch -moz-box-sizing (FF < 29 inkl. z. B. 17 und 24, die ESR sind) und -webkit-box-sizing (Android <= 3). Selbst caniuse kann im Standardfilter-Ansicht irreführend sein. Ich schätze, nur für alte Typen interessant, die immer noch ihren CSS von Hand tippen ;)
Wie sieht es mit der Leistung aus?
Der * Matcher ist der teuerste Matcher, der in CSS existiert, richtig?
Vielleicht sollten Sie das in Ihrem Artikel erwähnen – zumindest als Randbemerkung.
Der universelle Selektor (
*) ist so schnell wie ein einfacherh1- oderdiv-Selektor. Er wird nur dann schlecht in der Leistung, wenn Sie den Selektor verschachteln, wie z. B..something *.Die "kleine Anpassung" an Paul Irishs Version scheint bei HTML5-Elementen nicht zu funktionieren (zumindest bei mir). Das Element erbt das Box-Sizing-Layout nicht, hat aber box-sizing: inherit darauf. Irgendwelche Ideen, warum?
Also, anstatt box-sizing auf html anzuwenden und alle anderen Elemente erben zu lassen, bevorzuge ich immer noch
*,*:before,
*:after {
.box-sizing(border-box);
}
Sie müssen eine Demo erstellen, um das Problem zu zeigen. Die Elemente sollen box-sizing: inherit; auf ihnen haben, damit sie von ihrem Elternelement erben, was das Setzen eines box-sizing-Kontexts erleichtert. Es hat definitiv nichts damit zu tun, ob die Elemente "HTML5" sind oder nicht.
Ich denke, das ist etwas sehr kniffliges. Es wird vielen helfen, aber Blogger wie ich werden es schwierig finden, es zu implementieren. Trotzdem ein großartiger Ansatz.
Gibt es eine Eckecke, die mir unbekannt ist, bei der
*:before, *:afterbesser ist als nur:before, :after? Ich wäre nicht überrascht, wenn einige alte Browserversionen damit Schwierigkeiten hätten.@Tigt –
Wenn beide funktionieren, ist
*:beforewahrscheinlich besser, weil es explizit, beabsichtigt und lesbar ist.Ich wollte gerade diese Anregung zu meinem eigenen Boilerplate hinzufügen, aber haben wir uns darauf geeinigt?
Wenn Sie normalize verwenden, stellen Sie sicher, dass Sie input type="search" den border-box-Wert hinzufügen, da normalize "inherit" von dem content-box Standardwert erbt.
zum Beispiel
Sie müssen es nicht zu Ihrem CSS "hinzufügen", ändern Sie es einfach in normalize.css.
Es ist auf lange Sicht einfacher zu warten. Wenn Sie Probleme haben, wissen Sie, dass es nur eine Stelle gibt, an die Sie sich wenden müssen. Außerdem wurde normalize.css erstellt, damit wir es an unsere spezifischen Bedürfnisse anpassen können, nicht unbedingt, um es "wie es ist" zu lassen.
Ich ziehe es vor, die Verwendung von Drittanbieter-Tools nicht zu ändern, sei es normalize, jQuery usw.
denn wenn ich aus irgendeinem Grund ein CDN verwenden muss, würde dies meine Arbeit nicht beeinträchtigen.
Nun, Sie berühren hier zwei verschiedene Bereiche, plus den CDN-Teil.
Der Teil mit den „unterschiedlichen Bereichen“ ist, dass man normalerweise niemals, zumindest habe ich nicht gehört, dass der erste das tut oder davon weiß, die Kern-jQuery-Bibliothek bearbeitet. Oder überhaupt eine größere JavaScript-Bibliothek. Nochmals, ich habe niemanden gehört, der so etwas tut. Zumindest noch nicht.
Aber was das Bearbeiten einer CSS-Datei angeht, insbesondere von „Resets“ (ja, ich weiß, normalize.css ist kein Reset, also haben Sie Nachsicht), das ist etwas, das viele Webdesigner/Front-/Back-End-Entwickler üblicherweise tun.
Ich verstehe Ihren Standpunkt, dass man keine Drittanbieter-Assets bearbeiten sollte, aber es hängt alles von der Art des Assets ab, mit dem Sie es zu tun haben.
Auf der anderen Seite erwähnten Sie die Verwendung eines CDN, um diese Drittanbieter-Assets zu hosten. Das ist großartig.
Wenn Sie jedoch ein CDN verwenden, dann deshalb, weil Sie und/oder Ihr Team tatsächlich Zugriff darauf haben. Wenn Sie keinen Zugriff darauf haben, hosten Sie Ihre CSS-Dateien möglicherweise gar nicht erst darin, daher ist die Bearbeitung von normalize.css immer noch machbar.
„ändern Sie es einfach in normalize.css“
Ja, das meinte ich.