How to Specify a CSS Shorthand for "All Elements Except the First/Last"

Is there any way to specify a CSS shorthand for all elements except the first/last?

For all p elements except the first child, use either one of these (the second one is better-supported):

p:not(:first-child)
p:first-child ~ p

For all p elements except the last child:

p:not(:last-child)

For all p elements except the first and the last children:

p:not(:first-child):not(:last-child)

As usual, CSS3's :not() and :last-child aren't supported until IE9+ and relatively new versions of other browsers. You're not going to reach very far in terms of browser support (IE8 and older) unless you add classes to your first and last children, using JavaScript or otherwise.

Remember that vertical margins collapse between in-flow paragraphs and their ancestor(s), so unless you want to zero out the margins of the container element for these paragraphs as well, you shouldn't need to zero out the margins of the first and last p elements specifically. Here's a fiddle to illustrate.

Last-of-type selector works, while first-of-type doesn't?

It is important to know that :first-of-type, :last-of-type, etc don't really apply to classes, but rather to the element type they're attached to, li in this case.

It can be a bit confusing in the beginning, and sometimes if you follow good markup practices you may not even notice the difference since the elements are properly isolated, but it doesn't work like you'd expect from :first-of-class (which doesn't exist).

There are some ways around it, but none are perfect. My favorite answer is this one. Pretty well written and explained.

Using `:not(:last-child)` on child elements won't skip the real last element

From MDN:

The :last-child CSS pseudo-class represents the last element among a group of sibling elements.

It does not refer to the last of a particular class. The selector .blue:not(:last-child) matches all elements that are .blue and not the last child in the NodeList encapsulated by .box. In your example last-child means the second .red element.

It is not actually possible to select by the last of a particular class or selector. The closest we have is last-of-type which as the name suggests will select the last of a particular element type. For example:

h2:last-of-type {
color: red;
}
<h2>First Heading</h2>
<h2>Second Heading</h2>
<p>Paragraph 1</p>
<p>Paragraph 2</p>

Select only the first and the last link in divs

Selecting the first and last link

As your links are wrapped in div elements you'll need to select the first and last div and target the first or last a element within those:

.navigation_sub_item:first-child a:first-of-type {
/* The very first link. */
}

.navigation_sub_item:last-child a:last-of-type {
/* The very last link. */
}

Note that I've specified the first-of-type and last-of-type on the a elements themselves just in case more than one a element exists within your div elements. You may want to replace these with first-child and last-child if you do not care about other elements coming before or after them.


A special case for where only one element is present

I want them all, thats cool. But what should I do if there is only one .navigation__sub__link-element? then the :last-child rule will be applied but I want another rule to be used.

In that case you can override the specificity of these selectors by specifying both first-child and last-child:

.navigation_sub_item:first-child:last-child a {
/* This will override the above selectors. */
}

Or if you're not specifying :first-of-type or :last-of-type on your a elements, you could equally use the :only-child selector:

.navigation_sub_item:only-child a {
/* This will also override the above selectors. */
}

Reset/remove CSS styles for element only

The CSS3 keyword initial sets the CSS3 property to the initial value as defined in the spec. The initial keyword has broad browser support except for the IE and Opera Mini families.

Since IE's lack of support may cause issue here are some of the ways you can reset some CSS properties to their initial values:

.reset-this {
animation : none;
animation-delay : 0;
animation-direction : normal;
animation-duration : 0;
animation-fill-mode : none;
animation-iteration-count : 1;
animation-name : none;
animation-play-state : running;
animation-timing-function : ease;
backface-visibility : visible;
background : 0;
background-attachment : scroll;
background-clip : border-box;
background-color : transparent;
background-image : none;
background-origin : padding-box;
background-position : 0 0;
background-position-x : 0;
background-position-y : 0;
background-repeat : repeat;
background-size : auto auto;
border : 0;
border-style : none;
border-width : medium;
border-color : inherit;
border-bottom : 0;
border-bottom-color : inherit;
border-bottom-left-radius : 0;
border-bottom-right-radius : 0;
border-bottom-style : none;
border-bottom-width : medium;
border-collapse : separate;
border-image : none;
border-left : 0;
border-left-color : inherit;
border-left-style : none;
border-left-width : medium;
border-radius : 0;
border-right : 0;
border-right-color : inherit;
border-right-style : none;
border-right-width : medium;
border-spacing : 0;
border-top : 0;
border-top-color : inherit;
border-top-left-radius : 0;
border-top-right-radius : 0;
border-top-style : none;
border-top-width : medium;
bottom : auto;
box-shadow : none;
box-sizing : content-box;
caption-side : top;
clear : none;
clip : auto;
color : inherit;
columns : auto;
column-count : auto;
column-fill : balance;
column-gap : normal;
column-rule : medium none currentColor;
column-rule-color : currentColor;
column-rule-style : none;
column-rule-width : none;
column-span : 1;
column-width : auto;
content : normal;
counter-increment : none;
counter-reset : none;
cursor : auto;
direction : ltr;
display : inline;
empty-cells : show;
float : none;
font : normal;
font-family : inherit;
font-size : medium;
font-style : normal;
font-variant : normal;
font-weight : normal;
height : auto;
hyphens : none;
left : auto;
letter-spacing : normal;
line-height : normal;
list-style : none;
list-style-image : none;
list-style-position : outside;
list-style-type : disc;
margin : 0;
margin-bottom : 0;
margin-left : 0;
margin-right : 0;
margin-top : 0;
max-height : none;
max-width : none;
min-height : 0;
min-width : 0;
opacity : 1;
orphans : 0;
outline : 0;
outline-color : invert;
outline-style : none;
outline-width : medium;
overflow : visible;
overflow-x : visible;
overflow-y : visible;
padding : 0;
padding-bottom : 0;
padding-left : 0;
padding-right : 0;
padding-top : 0;
page-break-after : auto;
page-break-before : auto;
page-break-inside : auto;
perspective : none;
perspective-origin : 50% 50%;
position : static;
/* May need to alter quotes for different locales (e.g fr) */
quotes : '\201C' '\201D' '\2018' '\2019';
right : auto;
tab-size : 8;
table-layout : auto;
text-align : inherit;
text-align-last : auto;
text-decoration : none;
text-decoration-color : inherit;
text-decoration-line : none;
text-decoration-style : solid;
text-indent : 0;
text-shadow : none;
text-transform : none;
top : auto;
transform : none;
transform-style : flat;
transition : none;
transition-delay : 0s;
transition-duration : 0s;
transition-property : none;
transition-timing-function : ease;
unicode-bidi : normal;
vertical-align : baseline;
visibility : visible;
white-space : normal;
widows : 0;
width : auto;
word-spacing : normal;
z-index : auto;
/* basic modern patch */
all: initial;
all: unset;
}

/* basic modern patch */

#reset-this-root {
all: initial;
* {
all: unset;
}
}
  • Relevent github repo with a december 2017 more exaustive list
  • Related
  • Related from MDN
  • Related W3C specs

As mentioned in a comment by @user566245 :

this is correct in principle, but individual mileage may vary. For
example certain elements like textarea by default have a border,
applying this reset will render those textarea's border less.


JAVASCRIPT ?

Nobody thought about other than css to reset css? Yes?

There is that snip fully relevant : https://stackoverflow.com/a/14791113/845310

getElementsByTagName("*") will return all elements from DOM. Then you
may set styles for each element in the collection:

answered Feb 9 '13 at 20:15 by VisioN

var allElements = document.getElementsByTagName("*");
for (var i = 0, len = allElements.length; i < len; i++) {
var element = allElements[i];
// element.style.border = ...
}

With all this said; i don't think a css reset is something feasable unless we end up with only one web browser .. if the 'default' is set by browser in the end.

For comparison, here is Firefox 40.0 values list for a
<blockquote style="all: unset;font-style: oblique"> where font-style: oblique triggers DOM operation.

align-content: unset;
align-items: unset;
align-self: unset;
animation: unset;
appearance: unset;
backface-visibility: unset;
background-blend-mode: unset;
background: unset;
binding: unset;
block-size: unset;
border-block-end: unset;
border-block-start: unset;
border-collapse: unset;
border-inline-end: unset;
border-inline-start: unset;
border-radius: unset;
border-spacing: unset;
border: unset;
bottom: unset;
box-align: unset;
box-decoration-break: unset;
box-direction: unset;
box-flex: unset;
box-ordinal-group: unset;
box-orient: unset;
box-pack: unset;
box-shadow: unset;
box-sizing: unset;
caption-side: unset;
clear: unset;
clip-path: unset;
clip-rule: unset;
clip: unset;
color-adjust: unset;
color-interpolation-filters: unset;
color-interpolation: unset;
color: unset;
column-fill: unset;
column-gap: unset;
column-rule: unset;
columns: unset;
content: unset;
control-character-visibility: unset;
counter-increment: unset;
counter-reset: unset;
cursor: unset;
display: unset;
dominant-baseline: unset;
empty-cells: unset;
fill-opacity: unset;
fill-rule: unset;
fill: unset;
filter: unset;
flex-flow: unset;
flex: unset;
float-edge: unset;
float: unset;
flood-color: unset;
flood-opacity: unset;
font-family: unset;
font-feature-settings: unset;
font-kerning: unset;
font-language-override: unset;
font-size-adjust: unset;
font-size: unset;
font-stretch: unset;
font-style: oblique;
font-synthesis: unset;
font-variant: unset;
font-weight: unset;
font: ;
force-broken-image-icon: unset;
height: unset;
hyphens: unset;
image-orientation: unset;
image-region: unset;
image-rendering: unset;
ime-mode: unset;
inline-size: unset;
isolation: unset;
justify-content: unset;
justify-items: unset;
justify-self: unset;
left: unset;
letter-spacing: unset;
lighting-color: unset;
line-height: unset;
list-style: unset;
margin-block-end: unset;
margin-block-start: unset;
margin-inline-end: unset;
margin-inline-start: unset;
margin: unset;
marker-offset: unset;
marker: unset;
mask-type: unset;
mask: unset;
max-block-size: unset;
max-height: unset;
max-inline-size: unset;
max-width: unset;
min-block-size: unset;
min-height: unset;
min-inline-size: unset;
min-width: unset;
mix-blend-mode: unset;
object-fit: unset;
object-position: unset;
offset-block-end: unset;
offset-block-start: unset;
offset-inline-end: unset;
offset-inline-start: unset;
opacity: unset;
order: unset;
orient: unset;
outline-offset: unset;
outline-radius: unset;
outline: unset;
overflow: unset;
padding-block-end: unset;
padding-block-start: unset;
padding-inline-end: unset;
padding-inline-start: unset;
padding: unset;
page-break-after: unset;
page-break-before: unset;
page-break-inside: unset;
paint-order: unset;
perspective-origin: unset;
perspective: unset;
pointer-events: unset;
position: unset;
quotes: unset;
resize: unset;
right: unset;
ruby-align: unset;
ruby-position: unset;
scroll-behavior: unset;
scroll-snap-coordinate: unset;
scroll-snap-destination: unset;
scroll-snap-points-x: unset;
scroll-snap-points-y: unset;
scroll-snap-type: unset;
shape-rendering: unset;
stack-sizing: unset;
stop-color: unset;
stop-opacity: unset;
stroke-dasharray: unset;
stroke-dashoffset: unset;
stroke-linecap: unset;
stroke-linejoin: unset;
stroke-miterlimit: unset;
stroke-opacity: unset;
stroke-width: unset;
stroke: unset;
tab-size: unset;
table-layout: unset;
text-align-last: unset;
text-align: unset;
text-anchor: unset;
text-combine-upright: unset;
text-decoration: unset;
text-emphasis-position: unset;
text-emphasis: unset;
text-indent: unset;
text-orientation: unset;
text-overflow: unset;
text-rendering: unset;
text-shadow: unset;
text-size-adjust: unset;
text-transform: unset;
top: unset;
transform-origin: unset;
transform-style: unset;
transform: unset;
transition: unset;
user-focus: unset;
user-input: unset;
user-modify: unset;
user-select: unset;
vector-effect: unset;
vertical-align: unset;
visibility: unset;
white-space: unset;
width: unset;
will-change: unset;
window-dragging: unset;
word-break: unset;
word-spacing: unset;
word-wrap: unset;
writing-mode: unset;
z-index: unset;

CSS first-child and last-child don't work when used on the same element

I'm wondering why is that and if there is any workaround to that in CSS? It seems like CSS bug to me - first element can be also last element.

It's not a bug. It's how the cascade works: if an element is both the first child and the last child, then if you have :first-child and :last-child in separate rules and they both match the same element, then anything in the later declared or more specific rule will override the other.

You can find an example of this behavior here, with the border-radius shorthand property, and workarounds that include using the component properties instead of the shorthand, as well as specifying a separate rule altogether using one of the following selectors...

I'm looking for something like: "first child is also last child" selector. Does it exist?

Literally, you would chain both pseudo-classes like this, which works fine:

:first-child:last-child

However there exists a special pseudo-class that acts the same way:

:only-child

The main difference (in fact, the only difference) between these two selectors is specificity: the first one is more specific as it contains one additional pseudo-class. There is no difference even in browser support, as :last-child and :only-child are both supported by the exact same versions of each browser.

How to access inner elements of external components

This should work, but depending on how the external Select has the styles applied they might have a higher specificity and are still overriding the styles you applied. (see this article for a primer on how specificity works)

Without knowing which Select component you're using it's a bit hard to debug, but I'm assuming it uses inline styles (i.e. the style prop) which have a very high specificity and would thus override your applied styles.

There's two ways to bump specificity of your styles, both of which are not recommended if the external component doesn't use inline styles.

The first way to bump specificity is to use !important:

const StyledSelect = styled(Select)`
li {
margin-left: 20px!important;
}
`

In some cases that might not suffice, and it's also pretty tedious once you have more properties you need to forcibly override. A better way, but still not recommended way too it is to use the class hack: (notice the ampersands)

const StyledSelect = styled(Select)`
&&& li {
margin-left: 20px;
}
`

What styled-components does here is replace each of these & with the generated class, meaning the resulting CSS will look something like this:

.sc-asdf123.sc-asdf123.sc-asdf123 li {
margin-left: 20px;
}

These three classes massively bump the specificity of the styles within the block. That should do the trick!


To not style the first child you can use the first-child together with the not pseudo selector:

const StyledSelect = styled(Select)`
&&& li:not(:first-child) {
margin-left: 20px;
}
`

How to space the children of a div with css?

For an unknown amount of children you could use.

#parent > * {
margin: 30px 0;
}

This will add a top and bottom margin of 30px to all direct children of #parent.

But img is not displaying as block default, so you may use:

#parent > * {
display: block;
margin: 30px 0;
}

Vertical margins of block elements will be collapsed. But you will have margins at top and bottom of your parent div. To avoid that use the following code:

#parent > * {
display: block;
margin-top: 30px;
}

#parent > *:first-child {
margin-top: 0px;
}

This will only add top margin and removes that top margin for the first element.



Related Topics



Leave a reply



Submit