Omar Juvera
Omar Juvera

Reputation: 12307

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; } (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")


Upvotes: 36

Views: 39333

Answers (8)

marsidev
marsidev

Reputation: 61

You can achieve it with the :has() selector, as follows:

:has(main aside) {
  section {
    max-width: 500px;
  }
}

Upvotes: 1

wawa
wawa

Reputation: 5084

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 :(

Upvotes: 55

deowk
deowk

Reputation: 4318

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;
}

Upvotes: 5

Fares M.
Fares M.

Reputation: 1538

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()

Upvotes: 3

Sam Redway
Sam Redway

Reputation: 8157

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>

Upvotes: 0

COLD TOLD
COLD TOLD

Reputation: 13599

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

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

Upvotes: 0

Ga&#235;l Barbin
Ga&#235;l Barbin

Reputation: 3939

If you have the possibility to put your aside element before the section one, you can use the adjacent sibling selectors:

aside + section{ max-width: 500px }

Upvotes: 0

Matju
Matju

Reputation: 51

Even though it's not the neatest way of doing things, you can run on document ready javascript function, to check if aside tag exists, and inject an in-line css to the section tag accordingly.

Upvotes: 0

Related Questions