CSS: Select the first adjacent sibling

2019-02-07 19:52发布

问题:

I have an HTML list like so:

<ul>
  <li class="heading">Heading 1</li>
  <li class="heading">Heading 2</li>
  <li>Text Under Heading 2</li>
</ul>

Since Heading 1 has no text under it, I want to hide it with CSS.

If I do this,

li.heading + li.heading { display: none; }

it hides Heading 2 instead of Heading 1.

How can I hide Heading 1? Is there a way to look for adjacent siblings and select the first one?

回答1:

It is not possible using CSS as currently defined and implemented. It would require a selector that selects an element on the basis of its siblings after it. CSS selectors can select an element on the basis of preceeding or outer elements, but not on the basis of following or inner elements.

The desired effect can be achueved using JavaScript in a rather straightforward way, and you can decide, depending on the purpose, whether you just remove the elements from display or completely remove them from the document tree.



回答2:

It is possible to target first sibling with CSS, with some limitations.

For the example in the question it could be done with something like this

li.heading { display: none; }                   /* apply to all elements */
li.heading + li.heading { display: list-item }  /* override for all but first sibling */

This works, but requires that you can explicitly set the styles on the siblings to override the setting for first child.



回答3:

There are a few ways to hide only the "Heading 1" only:

ul li:first-child {display:none;}

Alternatively:

li.parent{ display: none; }
li.parent + li.parent { display: list-item; }

Also, <li>Child of Heading 2</li> is not a child of <li class="parent">Heading 2</li>. It is a sibling.



回答4:

The official CSS3 Spec does not currently support anything like this, though I do realize that it would be useful.

I would try doing searches for some prebuilt javascript or jquery scripts/libraries for adding css selectors. Although I have never come across anything.

If you do come across something, please post it here.

If you do not find anything, you might as well just do it manually, or try finding a completely different solution.

I wish I had a better answer for you. Sorry :(



回答5:

try using js to getElementsby Classname and if more than 1 then use css:

ul li:first-child {display: none;}



回答6:

I know that this question has already a valid marked answer, but maybe other people want to use my css-only solution:

I wanted to have a list of alerts (in this case bootstrap alerts) in a container and their border to collapse. Each alert has a border-radius, which looks rather silly when they are all in one container. So with margin-top: -1px I made their borders collapse. As a next step I had to modify the styles of the first, every alert in between and the last alert. And this should also look nice for a single alert, two alerts and n alerts.

.alert {
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    border-bottom-left-radius: 0px;
    border-bottom-right-radius: 0px;
    margin: 0;
}

// set for the first alert that it should have a rounded top border

.alert:last-child {
    border-bottom-left-radius: 4px;
    border-bottom-right-radius: 4px;
}

// set for the last alert that it should have a rounded bottom border
// if there is only one alert this will also trigger it to have a rounded bottom border aswell

.alert+.alert:last-child {
  margin-top: -1px;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

//for the last border of n alerts we set the top border to be collapsing and remove only the the top rounded borders

.alert+.alert:not(:last-child) {
  margin-top: -1px;
  border-radius: 0;
}

// for each following alert in between we remove the top rounded borders and make their borders collapse

And here is an angular template for multiple alerts.

<div id="alertscontainer">
    <div data-ng-repeat="alert in data.alerts" class="alert" data-ng-class="'alert-' + alert.class">
        {{alert.body}}
    </div>
</div>


回答7:

Use :first-of-type

You can read more here