Editor's Note: Suchen Sie nach einer moderneren Methode, um konsistente Abstände am unteren Rand zwischen Elementen zu erzielen? Heydon Pickerings „Lobotomized Owl“-Selektor ist eine gute Methode, während wir auf die Unterstützung der Eigenschaft margin-trim warten.
Ah, das bescheidene Modul! Viele Designs heutzutage nutzen Module sowohl in Content- als auch in App-ähnlichen Websites. Ein Informationsblock, eine Anzeige, eine gruppierte Funktionalität... das kann alles sein. Die Tatsache, dass sie wahrscheinlich visuelle Ähnlichkeiten aufweisen, aber alles enthalten können, führt zu einer interessanten CSS-Herausforderung: Wie polstert man das Innere konsistent?
Hier ist ein einfaches Beispiel, bei dem das Modul durch Farbunterschiede vom Hintergrund abgehoben wird
html {
background: #333;
}
.module {
width: 20rem;
padding: 1.5rem;
margin: 1.5rem auto;
background: white;
}
Aber sobald dieses Modul andere Elemente enthält, können die Abstände „verkehrt“ werden.
Modul
Pellentesque habitant morbi tristique senectus…
Der Absatz wird sehr wahrscheinlich einige globale Typografieregeln darauf angewendet bekommen, die sehr wahrscheinlich einen unteren Rand haben. Selbst wenn Sie sich für Opt-in-Typografie entscheiden, würden Sie sich hier wahrscheinlich dafür entscheiden, da Text vorhanden ist.
Sehen Sie die starke untere Polsterung? Vielleicht ist das in Ordnung für Sie, aber ich vermute nicht. Diese Schwere rührt von der konsistenten Polsterung, die Sie dem Modul selbst gegeben haben, *plus* dem unteren Rand des Absatzes.
Was tun wir also hier? Ein unsauberer Schnellschuss wäre, die Ränder dieser Absätze zu entfernen.
.module p {
margin: 0;
}
Aber ich bin sicher, wir sind uns einig, dass das ziemlich unschön ist. Was ist, wenn ein Modul zwei Absätze enthält? Jetzt stoßen sie unbeholfen aufeinander.
Vielleicht nur der letzte?
.module p:last-child {
margin: 0;
}
Das könnte funktionieren. Aber diese Lösung fühlt sich immer noch ein wenig nachgebastelt an. Was ist, wenn das Problem-Element eines Tages gar kein Absatz ist? Es könnte ein
-
- oder
-
-
- sein. Oder
-
- sein. Oder jedes andere HTML-Element... Werden wir jedes einzelne HTML-Element auflisten?
.module p:last-child,
.module ul:last-child,
.module ol:last-child,
.module dl:last-child {
/* losing battle */
margin: 0;
}
Das ist definitiv ein Kampf, den man verliert.
Aber wir könnten jedes Element ansprechen...
.module *:last-child {
margin: 0;
}
Sie könnten sogar das „*“ dort weglassen, da es impliziert ist und keine Spezifität hat, aber ich denke, es macht es klarer. Ich denke, das kommt einer guten Lösung nahe, aber es ist ein wenig übertrieben. Listen haben immer Kindelemente, die davon betroffen wären. Alles mit Nachkommen wäre ein Problem. Um das zu beheben, stellen wir nur sicher, dass nur das oberste Element unter dem Modul diese Behandlung mit dem Kindselektor erhält.
.module > *:last-child {
margin: 0;
}
Das ist in Ordnung. Ich würde es immer noch nicht perfekt nennen, da Nachkommen tatsächlich die Ursache für die zusätzliche untere Polsterung sein könnten. Zum Beispiel, wenn die Listenelemente Absätze enthalten. Sie könnten sie ein paar Mal verketten, um eine angemessene DOM-Tiefe zu erreichen.
.module > *:last-child,
.module > *:last-child > *:last-child,
.module > *:last-child > *:last-child > *:last-child {
margin: 0;
}
Das könnte es sein.
Hier ist eine visuelle Demo
Sehen Sie den Pen JFynD von Chris Coyier (@chriscoyier) auf CodePen
Ein völlig anderer Ansatz wäre, die untere Polsterung des Moduls wegzulassen und die Kindelemente dafür sorgen zu lassen, aber das erscheint mir etwas riskant, da keine Garantie besteht, dass das Kindelement seine eigene mitbringt (z. B. ein generisches
).
sind Sie darauf gestoßen? Haben Sie Ihre eigene bevorzugte Lösung?
Was ich gemacht habe, war genau bis zum vorletzten Codeblock. Habe mir keine Gedanken über das Verketten der DOM mehrmals gemacht, nur um sicher zu gehen. So oder so fühlt es sich gut an, zu sehen, dass wir die gleiche Lösung für all diesen lästigen Randkram haben.
Ich höre immer von der schlechten Performance des * Selektors. Ist es also nicht eine Bedrohung für die Leistung, ihn zu *verketten*?
Weiß jemand, wie stark sich das auf eine echte Webseite auswirkt?
@Luca R.: Ich benutze diese Methode immer und hatte nie Leistungsprobleme. Aber ich schätze, es hängt von der Komplexität des Projekts ab.
Luca – Ich denke, dass die Leistung des * Selektors mehr diskutiert wird, wenn man ihn auf JEDES Element einer Website anwendet, * {} zum Beispiel. Und selbst dann bin ich mir ziemlich sicher, dass es hier schon mal behandelt wurde, dass es keine absolut schlimme Auswirkung auf die Leistung hat.
Nun, das sind gute Nachrichten. :)
Ich bin definitiv darauf gestoßen, habe aber etwas Ähnliches wie Ihre ersten Iterationen der Korrektur verwendet, nur um später festzustellen, dass ich den Kampf verlor. Und dort habe ich aufgegeben.
Vielen Dank, dass Sie etwas Licht ins Dunkel gebracht haben!
Hallo Chris, was ist mit Folgendem?
http://codepen.io/catalinred/pen/yHsop
.module *:last-of-type {
margin: 0;
}
Sieht so aus, als würden Sie den Rand des h3 verlieren, der wahrscheinlich der letzte seiner Art in einem Modul ist, aber unwahrscheinlich das letzte Kind ist.
Yep, das habe ich gerade gesehen, nachdem ich die Antwort gepostet hatte. Ich war so nah dran! :)
Ich würde das so machen
.module *:last-child {
margin-bottom: 0;
}
Beispiel hinzugefügt
Ja! Ich habe diesen Code gerade verwendet, um das Problem mit den Abständen am unteren Rand zu lösen, und bin auf andere Abstandsprobleme gestoßen, da alle Ränder entfernt wurden.
margin-bottom: 0ist der richtige Weg!Der Artikel geht diesen Weg nicht, weil er „ein wenig übertrieben“ ist. Gibt es eine Möglichkeit, ohne das Verketten von Kindselektoren zu optimieren?
Das ist genau das, was ich in der Vergangenheit gemacht habe. Ich habe nicht an Nachkommen gedacht, aber das Problem ist nie aufgetreten. Es ist eine schöne Lösung :)
Ich löse das normalerweise auf zwei Arten
1. Dem Modul weniger Polsterung oben und unten geben, was durch die Ränder des Inhalts ausgeglichen wird.
2. Eine 1 Pixel Polsterung am unteren Rand des Containers setzen (falls der Rand des Inhalts dem des Containers entspricht).
Nummer 2 ist ein wenig „gebastelt“ und sollte nur verwendet werden, wenn Sie die volle Kontrolle über den Inhalt des Containers haben (und sicher sind, dass das Layout sich nicht ändert).
:last-child funktioniert nicht gut mit IE8 (obwohl Sie IE8 vielleicht nicht vollständig unterstützen wollen).
Alternativ können Sie allen Inhalten nur einen oberen Rand geben. Dann können Sie :first-child ansprechen oder eine OOCSS-Klassenstruktur verwenden (aber das ist mehr Markup).
Nur der obere Rand ist auch nicht ganz schön. Normalerweise möchten Sie entweder obere und untere Ränder oder zumindest den unteren, aber ich schätze, es ist eine Option.
So etwas wie das: http://jsfiddle.net/ReinierK/CwReR/
Das einzige Problem bei Nr. 1 ist, wenn Sie ein Element haben, das *keinen* Rand hat (wie ein div).
Wenn Ihr Inhalt nur in einem
<
div> eingewickelt ist, haben Sie sowieso andere Probleme mit der Barrierefreiheit.
Ich habe immer den Schnellschuss-Ansatz verfolgt,
.module p:last-child { margin: 0; }, und dann darauf geachtet, ob ich später verschachtelte Elemente hinzufüge und diese dann verwalte. Ziemlich chaotisch und ineffizient. Ich bin auch an einer besseren Methode interessiert!Was ich normalerweise mache, ist, den oberen Rand zu benachbarten Geschwisterelementen hinzuzufügen, anstatt den unteren Rand zu jedem Element. Ich verwende so etwas wie
p + p { margin-top: 1em; }Ich passe das je nach Inhalt des Moduls an. Es funktioniert meistens gut.
Das ist eine Killeridee, das muss ich mir merken.
Diese Methode habe ich auch verwendet. Funktioniert gut bei Absätzen, aber es ist schwierig (und wortreich), sie kugelsicher für alle möglichen Kombinationen von benachbarten Elementen zu machen.
Ich wollte genau das Gleiche vorschlagen.
Wir verwenden diese Technik bei der Arbeit. :)
Der beste Ansatz bisher. :-)
Mir zuvorgekommen!
Ich halte es für wichtig, nur den `margin-bottom` zu nullen... Es könnte ein wichtiges Layout-Element innerhalb des Moduls gestört werden, indem seine oberen, linken und rechten Ränder gelöscht werden, wenn wir uns eigentlich nur um den unteren Abstand kümmern. Aber eine ausgezeichnete Technik!
Hallo Chris,
Ich bin nur neugierig auf Ihre Verwendung des Universal-Selectors – tut er etwas im Beispiel? Hilft er oder schadet er der Leistung? Was ist mit dem Entfernen: http://codepen.io/mikevoermans/pen/ILida
Nur neugierig auf Ihre Gedanken.
Eine weitere Lösung ist die Verwendung zusätzlicher Klassen
// Ränder für erste/letzte Elemente entfernen
.first { margin-top: 0 !important; margin-left: 0 !important; }
.last { margin-bottom: 0 !important; margin-right: 0 !important; }
Ich verwende sie, wenn ich weiß, dass das Hinzufügen von :last-child überflüssig ist, z. B. weil ein Fall besonders ist und die Regel auf ein Element auf der gesamten Website zutreffen würde.
Ja, das ist genau das, was ich mir gedacht habe. Es ist besser, sich auf Klassen zu verlassen als auf fortgeschrittene Selektoren, auch wenn es umständlicher ist, obwohl ich argumentieren würde, dass dies in diesem Fall eleganter ist.
Nun, ich sage „besser“. Ich meine, ich *fühle*, dass es besser ist, sich auf Klassen anstatt auf fortgeschrittene Selektoren zu verlassen. Ich denke, fortgeschrittene Selektoren funktionieren besser in einer Atmosphäre, in der man die Kontrolle über den Inhalt hat, d.h. einer persönlichen Website.
Nicht wirklich. Wenn der Modulinhalt aus einem CMS stammt, wie fügen Sie die ersten und letzten Klassen hinzu?
Sie müssen es über das Backend oder JavaScript einfügen.
Die fortgeschrittenen Selektoren funktionieren gut, wenn der Inhalt aus einem CMS stammt.
Ich hasse es, wenn ich ein Redesign-Projekt bekomme und das vorherige HTML beibehalten muss, aber es ist voller zusätzlicher Klassen, wie z. B. „clearfix“ überall.
Das HTML muss einfach genug sein, damit CSS jederzeit ersetzt werden kann. Zu viele zusätzliche Klassen zu verwenden, ist keine gute Idee.
Zumindest in diesem Fall werden die ersten und letzten Klassen nichts bewirken, wenn ich das CSS ersetze.
Warum keinen negativen Rand am unteren Rand von .module verwenden?
Haben Sie das ausprobiert?
Das Problem liegt nicht beim Modulrand, sondern bei der Modulpolsterung.
Ich denke, das sollte auf Kosten eines :after-Pseudo-Elements funktionieren (was möglicherweise bereits in Ihrem realen Markup berücksichtigt ist).
Hier ist ein Link zu Ihrem modifizierten Codepen mit der implementierten Lösung. Habe es noch nicht in allen Browsern getestet. Der obere Rand muss größer sein als jeder untere Rand eines enthaltenen Elements und erzwingt einen Spaltenkollaps mit dem letzten Element, sodass Sie einen konsistenten zusätzlichen Platz am unteren Rand jedes Moduls haben. Der untere negative Rand kompensiert diesen kollabierten Rand, indem er ihn schluckt. Ich greife oft auf negative Ränder für solche Tricks zurück.
Diese Lösung gefällt mir sehr gut. Soweit ich sie verstehen kann, ohne sie zu testen (ich bin gerade am Handy), berücksichtigt sie den unteren Rand jedes letzten Elements (sogar Enkel), schluckt diesen Rand dann mit ihrem eigenen negativen Rand wieder auf, richtig? Genial; ich freue mich darauf, es auszuprobieren. Box-Formatting-Kontexte sind ein Dorn in meinem Auge, und ich habe mich immer unwohl gefühlt, mich auf das Styling des letzten direkten Nachkommen zu verlassen – oder einer Kette von letzten Nachkommen von letzten Nachkommen von letzten Nachkommen. Es schien immer zu zerbrechlich und auf vorhersagbares Markup angewiesen. Dieses hier funktioniert einfach – es sei denn, einer der Nachkommen erstellt seinen eigenen Block-Formatting-Kontext und verhindert den Randkollaps.
Diese Lösung gefällt mir sehr gut, allein wegen der Verwendung des :after-Pseudo-Selectors. Ich schätze, das würde mit IE 8 und höher funktionieren.
Warum nicht einfach jedem zweiten Element einen oberen Rand geben? So etwas wie
.module > * ~ * {padding-top:1em} // jedes Kind nach dem ersten ElementDadurch trennt man die Dinge und hat keine untere Polsterung?
Ich verwende
.module > :last-child { margin-bottom: 0; }+ eine generische Hilfsklasse.vertical-rhythm--none { margin-bottom: 0; }für verschachtelte oder spezielle Fälle. Ich wende vertikale Ränder nur in eine Richtung an (nach unten).Ich denke, das ist die beste Lösung bisher.
Ich bin ein großer Fan von einseitigen Rändern, das macht alles unglaublich vorhersehbar! Ich habe es zuerst von CSS Wizardry gehört.
Ich verwende den folgenden Code im Cascade Framework, um die zusätzliche Polsterung über die Grid-Struktur der Website zu bewältigen
.cell>:last-child {
margin-bottom: 0;
}
Ich habe mich für
margin-bottom : 0anstelle vonmargin: 0entschieden, da der Selektor zu generisch ist, um auch für obere, linke und rechte Ränder einen Reset durchzuführen.Ich bin nur eine Ebene nach unten gegangen, aus demselben Grund. Ich möchte vielleicht einen unteren Rand für die Kindelemente des Elements oder deren Kinder. Bei einem solch generischen Anwendungsfall ist es unmöglich zu wissen. Und wenn Sie wirklich einen Rand-Reset für die Kinder der Kinder und so weiter benötigen, erscheint es mir besser, einfach klassenbasierte Selektoren zu verwenden, um sie anzupassen.
Ich neige dazu, dies einmal für alle Blockelemente auf der grundlegenden Typografieebene zu tun, anstatt auf Modulebene, z. B. (Sass)
p
margin-bottom: 2em
&:last-child
margin-bottom: 0
Fälle, in denen ich tatsächlich möchte, dass ein
p,uloderol, das ein:last-childist, diesen unteren Rand hat, sind selten und weit verteilt, daher ist es einfach und sinnvoll, diese Ausnahmefälle auf Modulebene zu überschreiben.ups, die Formatierung ist hier kaputtgegangen, aber Sie verstehen, was ich meine :)
Eine echte vertikale Zentrierung sieht oft „falsch“ aus. Deshalb sieht man im Druck oft, dass sie etwas nach oben verschoben ist. In meinen Augen sieht Ihre „starke untere Polsterung“ besser aus als gar keine Polsterung.
Wow, viel ordentlicherer Ansatz als meine Methoden... werde das von nun an verwenden. Danke!
Wenn das nur mit Logik in CSS selbst geprüft werden könnte, wie eine Media Query.
Ich füge normalerweise oben Rand/Polsterung hinzu
.module p {margin: 20px 0 0;
}
Hier ist ein Beispiel.
Oder einfache Mathematik
$mod-bottom-padding: 1.5rem;$mod-element-bottom-margin: 1rem;
.module {
padding-bottom: $mod-bottom-padding - $mod-element-bottom-margin;
}
Ok, wenn Ihre Modulelemente alle denselben unteren Rand haben.
Was ist mit kollabierenden Rändern und Pseudo-Elementen? Siehe
http://codepen.io/getdave/details/gfEiq
Wir erstellen ein Pseudo-Element, weisen ihm einen oberen Rand zu, der dann in den unteren Rand des letzten Elements „kollabiert“. Funktioniert am besten, wenn die Modulpolsterung auf der Grundlinienhöhe/-rand basiert.
Wow, das ist clever! Es scheint ziemlich narrensicher zu sein, da es auf der Logik des Randkollapses basiert, anstatt mit CSS-Selektoren doppelt zu raten. Gibt es Fälle, in denen es nicht funktioniert?
Das ist brillant! Braucht man die Höhe 1px? Erscheint der Rand immer noch, wenn er `display: block` ist, auch wenn keine Höhe vorhanden ist?
Meiner Meinung nach ist die einzig vorhersagbare, nachhaltige Lösung, dass das Markup beschreibender ist. Durch die Spezialisierung des Modulklassennamens können Sie Ihren Designanforderungen auf unkomplizierte, idiomatische (und performante) Weise gerecht werden. Demo-Stift.
(Es gibt andere Möglichkeiten, das Markup anzureichern. Sie können das Modul allgemein halten, aber den Inhalt in ein Element einwickeln, das eine spezialisierende Klasse hat. Z.B. im Wesentlichen
<module><module-titled-list><h3/><ul/></module-titled-list></module>oder<module><module-list><ul/></module-list></module>.)Das Argument, dass Module gedankenlose, generische Zombies sein sollten, ist eine interessante, aber künstliche Hypothese. Jedes CMS oder jede App, die dieses Modul rendert, kann so erweitert werden, dass der Typ bei der Inhaltseingabe angegeben wird. Wenn Sie die App oder das, was die Struktur rendert, nicht ändern können, haben Sie ein viel größeres Problem, das Ihr Design betrifft.
Danke für den interessanten Beitrag.
Ich gebe zu, dass ich normalerweise den Weg des verlorenen Kampfes wähle. Ich habe jedoch nach dem Lesen dieses Artikels beschlossen, dass mein CSS etwas generischer sein muss. Danke für die interessante Lektüre.
Ich schlage vor, nur den oberen Rand für allgemeine Abstände zu verwenden, denn bei der Planung einer bestimmten Seite weiß man meistens, welche Inhalte am Anfang der Seite stehen werden. Man weiß normalerweise nicht, wie eine Seite enden wird – wird es eine Paginierungskomponente geben, Aktionsschaltflächen, Autoreninformationen oder was auch immer (abhängig von der Dynamik der spezifischen Vorlage). Auf diese Weise können Sie die gesamte Seite wie ein Zugset arrangieren – die Lokomotive ist die erste ohne Dämpfer und jeder folgende Waggon hat seinen eigenen Abstandshalter, der nur für diesen speziellen Gegenstand konzipiert ist. Das erste Element der Seite ist zu 99 % dasselbe, eine Überschrift oder ein Breadcrumb, also muss man sich im Grunde nur darum kümmern. Wenn man sich nur auf eine Seite Abstand konzentrieren muss, ist es einfacher, dem allgemeinen Designraster/-abständen zu folgen.
Ich verwende seit Jahren nur den oberen Rand für Abstände und hatte nie Probleme mit diesem Ansatz. Also nur um eine Besonderheit zu erwähnen – IE7 unterstützt first-child: (damit kann man es verwenden) und unterstützt last-child nicht.
Ich setze alle meine oberen Ränder auf 0 und verwende nur den unteren Rand à la vertikale Rhythmen. Ich würde die untere Polsterung des Moduls auf 0 setzen, da jedes enthaltene Element einen unteren Rand hat.
Diese Technik verwende ich seit Jahren und hatte nie Probleme mit starker Polsterung.
Ich habe die untere Polsterung des Moduls schon immer weggelassen.
Die meisten Inhaltselemente benötigen unten Polsterung/Rand und wenn Sie Layout-Divs mit diesem Gedanken verwenden, geben Sie ihnen auch etwas unten Liebe. Außerdem werden Sie fast nie ein Modul mit einem H3 etc. beenden.
Ich gehe damit mit Sass um, indem ich es abstrakt halte, damit ich es für jedes Modul wiederverwenden kann, das es benötigt
%last-child { & > :last-child { margin-bottom: 0; } }
Wenn ein Modul den `margin-bottom` seines letzten Kindelements entfernen muss
.module { @extend %last-child; }
Wenn das
.moduleimmer ein Element enthält, das einenmargin-bottomhat, und dessen Rand gleich oder größer als die internepaddingist, dann setzen Sie die.module-padding-bottomauf1px, anstatt denmargin-bottomauf allen „letzten“ Elementen zurückzusetzen.Wenn man die Semantik über Bord wirft, benutze ich oft einige Helfer
.remove-margin-bottom {
margin-bottom: 0 !important;
}
Und in anderen Fällen
.give-margin-bottom {
margin-bottom: $spacing-variable !important;
}
Klingt vielleicht furchtbar, aber es gibt zu viele Fälle, in denen ich ein Element nur mit einer Klasse versehe, um einen unteren Rand zu entfernen oder hinzuzufügen. Fühlen Sie sich frei zu hassen. ;)
Nebenbei bemerkt, könnte es nützlich sein, eine Art rekursive Selektoren zu haben. Zum Beispiel
:last-child-recursive {margin-bottom: 0; }
würde automatisch den unteren Rand für das letzte Kind, das letzte Kind dieses letzten Kindes usw. für *alle* verschachtelten letzten Kinder nullen – unabhängig von der tatsächlichen Verschachtelungsebene.
Es gibt eine Nachricht auf der Mailingliste www-style zu dieser Idee.
Was passiert, wenn ein Designer kommt und einen Header mit einer Hintergrundfarbe oder einem Bild möchte, der am Rand des Moduls beginnt? Jetzt müssen Sie einen negativen Offset verwenden, was wohl für nur ein Element in Ordnung ist...
Ich lasse das hier
Clever, da es Randkollapse zur Behebung des Problems nutzt. Würde gut funktionieren, wenn der Rand/die Polsterung in den meisten Fällen gleich ist und die Kinder nicht gefloatet/inline-block sind.
Ich würde eine zusätzliche Klasse wählen, da sie meine Absicht, die Polsterung für dieses Element zu entfernen, klarer ausdrückt. Mit etwas wie _spaces.sass und dem Entfernen aller Ränder und Polsterungen aus den Kernmodulstilen. Dann hätten Sie eine Abstandskomponente mit wiederverwendbaren Rand-/Polsterungsklassen wie .l-pbn (padding bottom none) oder .l-mls (margin left small) usw.
{ margin-top: 10px; }
Würde jedem Kindelement einen oberen Rand geben, außer dem ersten Element, was das Problem ebenfalls löst. Eine weitere Lösung wäre die Verwendung eines Elements mit einem Rand anstelle einer Polsterung und die Nutzung von kollabierenden Rändern.
Chris, benutze nicht
.module > *:last-child{
//
}
verwenden
.module > :last-child{
//
}
es ist schneller und sauberer
So ein kleines dummes Problem, über das ich viel nachdenke. Danke für die Zusammenfassung, Chris! Ich baue normalerweise für die IE8-Unterstützung, daher verwende ich meistens `margin-top` und nulle es mit `first-child` aus, wenn ich es brauche.
Ich bin definitiv darauf gestoßen. Tolle Lösungen!
.module *:nth-last-child(1) { margin-bottom: 0; }Ups, das macht dasselbe wie
:last-child. Vergiss es.nth-child ist nicht IE8-freundlich
Es wäre besser, die `!important`-Regel zu verwenden.
Siehe http://jsfiddle.net/guimihanui/9hCdC/
Nein.
Diese Art von Code mag sehr einfach aussehen, aber es ist ein großartiger Code zur Verwendung und hat viele Anwendungen. Danke fürs Posten.
Warum nicht bei `.module :last-child` belassen?
spezifizierte Regeln werden diese höchstwahrscheinlich überschreiben; z.B.: `.module ul li { padding: 10px}`
Außerdem neige ich dazu, die von Sugareina erwähnte Methode zu verwenden, da der Selektor für benachbarte Geschwister weitaus abwärtskompatibler ist als `:last-child`.
MHO
Manchmal verwende ich den `:not`-Selektor wie folgt:
.my-spacing-element:not(:last-child) { margin-bottom: 15px; }Man könnte auch so etwas tun:
.container { padding: 5px 20px 20px; }.container > h1 { margin-top: 15px; }
.container > p { margin-top: 10px; }
.container > [jedes andere Element, das Sie benötigen könnten] {margin-top: [etwas]px; }
Vorausgesetzt, der Container beginnt immer mit einem `h1`, erhalten wir hier einen schönen Abstand von 20px auf jeder Seite innerhalb des Containers, während vor jedem `p` ein Abstand von 10px besteht (15px vor jedem `h1`, außer dem ersten, was sinnvoll ist, da der Containerabstand konsistent ist) und Sie müssen das erste oder letzte Element im Container nicht anders stylen als die anderen.
Für die meisten Situationen, in denen ich mich befinde, ist das ausreichend. Andererseits entwickle ich normalerweise keine Websites, auf denen ein einzelner Container an jeden einzelnen verdammten Elementtyp anpassbar sein muss, den der Kunde am Anfang des Containers unterbringen möchte. :D
.module > * {margin:1em;}
Bietet ein schön beabstandetes Raster für alle Kinder. Der Rand kann bei Bedarf von einzelnen Elementen zurückgezogen werden. Ich benutze das seit etwa 5 Jahren, das einzige knifflige ist, wenn `.module` keine Ränder hat und Ränder zu kollabieren beginnen. Ein clearfix oder `overflow:hidden` kann das beheben, aber das ist immer noch etwas hacky.
Mit einigen Pseudoelementen könnte man eine zuverlässige Lösung schaffen, ohne Kindelemente zu modifizieren. Schauen Sie mal hier.
Oben: Eigenständige Eleganz
Hier ist der Codepen noch einmal: http://codepen.io/thejameskyle/pen/pthGd (Schauen Sie sich unbedingt auch das Mixin an, das ich dort erstellt habe!)
Ich würde einfach den unteren Abstand des Containers weglassen. Das ist für mich der direkteste Weg, da es mir sehr unangenehm wäre, etwas zu verwenden, das den `*`-Selektor enthält. Außerdem wird `:last-child` in IE8 nicht unterstützt – was heutzutage immer unwichtiger wird, aber es ist ein Nachteil, den man nicht vergessen sollte.
Hallo Chris, nette Technik!
Ich habe es ein wenig modifiziert, um
first-childeinzuschließen, so:.module > *:first-child,.module > *:first-child > *:first-child,
.module > *:first-child > *:first-child > *:first-child {
margin-top: 0;
}
.module > *:last-child,
.module > *:last-child > *:last-child,
.module > *:last-child > *:last-child > *:last-child {
margin-bottom: 0;
}
Das einzige Problem, das ich sehe, ist, dass es nicht vollständig IE8-kompatibel ist.
Ich habe eine andere Lösung, die keine Entfernung von überschüssigem Leim erfordert.
Überschüssiger Leim??
Ich erkläre: Wenn Sie untere Ränder verwenden, bleibt das letzte Element immer mit einem Rand zurück, der es von nichts trennt. In der angebotenen Lösung wird dieser Rand immer angebracht und muss dann wieder entfernt werden, wie überschüssiger Leim.
Der von mir für „Module“ verwendete Code verwendet stattdessen den oberen Rand, aber nur bei Elementen, die anderen Elementen folgen.
.module * + * { margin-top: 1.5em }Das bedeutet: „Jedes Element, dem ein beliebiges Element vorausgeht, sollte durch einen oberen Rand getrennt werden.“ Leim wird nur aufgetragen, wenn er benötigt wird.
Dies funktioniert bei einer unendlichen Anzahl von Verschachtelungsebenen, da zwar jedes verschachtelte Element den oberen Rand erhält, aber kein erstes Kind. Keine verdoppelten Ränder, um die man sich Sorgen machen oder die man antizipieren müsste.
Da `:first-child` eine tiefere Unterstützung in älteren IE-Versionen hat, habe ich mir vor langer Zeit angewöhnt, Ränder und Innenabstände nur an den Oberseiten von Elementen anzuwenden und sie von den ersten Kindern zu entfernen. http://stackoverflow.com/questions/7938521/browser-support-for-css-first-child-and-last-child
Hier ist eine weitere semi- bis suboptimale Lösung, die wir hinzufügen können. Sie fügt keine neuen Elemente hinzu.
Der Vorteil ist, dass dies jede Verschachtelungsebene bewältigt, selbst wenn Nachfahren das Randkollabieren ihrer eigenen Nachfahren verhindern (floated children, children with
overflow: hidden, children with padding or border, etc.).Der Nachteil ist, dass sie erwartet, dass alle Ihre Kinder die gleiche Randgröße haben (in diesem Fall 1em).