简体   繁体   中英

CSS: Select element only if a later sibling exists

In my HTML structure, I have it set up like this:

<body>
   <main>
      <section>
      ...
      </section>

      <aside>
      ...
      </aside>
   </main>
</body>

The problem is, not all pages have <aside>

I need to select <section> and give it a max-width: 500px; ONLY when <aside> is present . The default is section { max-width: 1000px; } section { max-width: 1000px; } (when <aside> is absent)

Unlike in Selector for one tag directly followed by another tag ; the user [asking the question] wants to style "B" ALL the time. Also, in this question, the user wants to select "B" (not "A")


  • I need to style <section> ONLY if <aside> is present.
  • I can't change the order of the HTML >_<
  • Can it be done with CSS only?
  • What selector do I need or how to set it up?
  • If it can't be done with CSS (I rather it be CSS-only), how can I accomplish this?

A neat little trick

You can achieve what you want by using a trick to check if the <section> element is the only element in <main> . This will not work, if there are any other elements there. In your case it should work like this ( http://jsfiddle.net/Ljm323qb/2/ ):

section {
     max-width: 500px;
}
/* The STAR of the show */
section:only-child {
     max-width: 1000px;
}

As illustrated in this codepen: http://codepen.io/omarjuvera/pen/ByXGyK?editors=110


General stuff on Sibling Selectors

There's the + selector which would select a sibling that comes right after the element ( https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors )

And there's the ~ selector which selects all following siblings ( https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_selectors )

You could achieve it by putting the <aside> element before the <section> element and using a sibling selector.

Here's an example: http://jsfiddle.net/Ljm323qb/1/

A quick look in the future
Soon this will be possible, with a new :has pseudo class ( http://dev.w3.org/csswg/selectors-4/#relational )
You'll be able to call something like main:has(> aside) > section { ... } but we'll have to wait for that, unfortunately :(

WITHOUT JAVASCRIPT

If you can change the order of your html elements to:

<body>
   <main>
      <aside>
      ...
      </aside>

      <section>
      ...
      </section>
   </main>
</body>

You can do it like this by using a sibling selector:

aside ~ section {
    max-width: 500px;
}

You can toggle a class .haveSidebar to the body tag using jQuery and make your CSS for the section tag depends whether this class exists on the body tag or not:

HTML

<main>
    <section>
    </section>

    <aside>
    </aside>
</main>

CSS

main {
    width:100%;
}
main aside {
    width:300px;
    background:red;
    min-height:300px;
    float:left;
}
main section {
    width:100%;
    background:green;
    min-height:300px;
    float:left;
}
body.haveSidebar main section {
    width: calc(100% - 300px);
}

JS

var sideBar = $('body > main > aside');
if (sideBar.length > 0) {
    $('body').addClass('haveSidebar');
} else {
    $('body').removeClass('haveSidebar');
}

Fiddle with aside tag

Fiddle without aside tag

Update

Solution without calc() , by using margin-left property

main aside {
    width:300px;
    background:red;
    min-height:300px;
    position:relative;
}
main section {
    width:100%;
    background:green;
    min-height:300px;
    float:left;
}
.haveSidebar main section {
    margin-left:301px;
}

Fiddle without calc()

尽管它不是最好的做事方式,但您可以运行文档就绪的javascript函数,检查是否存在标记,并相应地向section标记注入内联css。

It would be fairly straightforward to accomplish this with JavaScript.

For example this will work:

<script>
    window.onload = function() {
        if (document.getElementsByTagName('aside')[0]) {
           document.getElementsByTagName('section')[0].style.max-width = '500px';
        } else {
            document.getElementsByTagName('section')[0].style.max-width = '1000px';
        }
    }
</script>

Try this, i believe it can only be done with some javascript.

if ($('main').find('aside').length>0)
{
    $('main').find('section').addClass('specificSection');
}

In CSS there is Adjacent sibling selectors: http://www.w3.org/TR/CSS21/selector.html#adjacent-selectors

section + aside { ... }

This is supported by all modern browsers, including IE8+ And be careful: selector matches if section and aside share the same parent in the document tree and section immediately precedes aside

If this doesn't work for you, you may try JavaScript with jQuery:

if($('aside').length)) $('section').addClass('specificSection');

And then add all your styles to class '.specificSeciton'.

如果你有可能把你的旁边元素放在第一部分之前,你可以使用相邻的兄弟选择器

aside + section{ max-width: 500px }

Using jQuery, you could try something like:

if($('aside')) $('section').css('max-width','500px');

Using CSS only, you could have a different style for the type of page that has the aside included and somehow only include that style on those pages. You could put that style into a little stylesheet of its own and include it where needed, which is probably a cleaner way of doing it than rendering the page and then changing it using JavaScript.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM