2

I'm trying to figure out a way to use CSS selectors to isolate a specific child of a div.

I want the selector to apply only to the input nested within #section1 and not within #section2.

<div class="section" id="section1">
    <div class="section" id="section2">
        <input type="text">
    </div>
    <input type="text">
</div>

This is a simplified example, but here are some notable things:

  • the divs are uniquely identifiable but have a common class
  • the two inputs are exactly identical in every way (except for their location), but each div.section only has unique inputs that aren't further nested within other div.sections
  • the location of a div.section's input could change, meaning that it could come before or after the nested div with an identical input (ruling out :nth-child(n) or :nth-of-type(n)) but it will still be in the level
  • there are a mess of other divs in and surrounding all of this code for formatting reasons
  • I didn't write the code and I can't change the code

If it's relevant, I'm using WebdriverIO to interact with the page, but it doesn't include much else except CSS selectors to find elements on the DOM (except for linking text, which isn't very useful here).

Let me know if I can clarify the scenario more. I couldn't find any questions similar enough to this (most were for styling and could be resolved by overriding the styling for the nested one) but please let me know if I missed something.


Edit: A more accurate example (with the complicated mess and extra inputs) looks more like this...

<div class="section" id="section1">
    <div>
        <div class="section" id="section2">
            <input type="text" class="input1">
            <input type="text">
        </div>
    </div>
    <div>
        <div>
            <div class="section" id="section3">
                <input type="text">
                ...
            </div>
        </div>
    </div>
    <div>
        <input type="text" class="input1">
        ...
    </div>
</div>
<div class="section" id="section4">
    ...
</div>

In this example, both input.input1 are children of #seciont1, but I want them to be associated with their nearest parent div.section. So the first occurring one would be associated with #section2 and the second with #section1.

So there could necessarily be extraneous code nested or surrounding any parts, but it is distinguishable for the important stuff. I just can't use the child selector > because it won't be a direct child.

There can also be more div.sections nested in any which way with more input, but there will only be unique inputs within each div.section that isn't further nested within a different div.section.

I'm also not using it for styling, so I can't overwrite with a second selector. I need the one selector to uniquely identify the correct input with it's closest parent div.section.

MDMazzullo
  • 21
  • 2

4 Answers4

0
#section1 > input { }

The > is the child selector. It only selects those elements that are immediate children of the element. It does not travel further down the tree.

sn3ll
  • 1,629
  • 1
  • 10
  • 16
  • The problem with that is that there are a ton of extra `div`s surrounding the input for formatting so it won't be a direct child. – MDMazzullo Jun 12 '17 at 23:36
0

You can do something like this

.section > #section1 input {
border: 2px solid red;
}

.section > #section1 > #section2 input {
    border: 2px solid green;
}

There is a pen for this way https://codepen.io/KamilNaja/pen/JJKKZx The second way is use "not" pseudoselector.

Kamil Naja
  • 6,267
  • 6
  • 33
  • 47
  • Right, but as I said I'm not using it for styling so I can't overwrite with a second selector. I need the one selector to uniquely identify the correct element. – MDMazzullo Jun 12 '17 at 23:37
0

Edit: I'm not sure you're going to cover all your cases with one magic bullet selector. (JavaScript might be able to, though.) What you really are trying to do is pick an input based on one of its parents (or grandparents, or great-grandparents, or whatever). But this is not possible in CSS.

See: Is there a CSS parent selector?

However, you could probably get what you want with some clever combinations of selectors. Helpful options you can mix and match:

  • # ID selector
  • > direct child selector
  • :nth-child/:nth-of-type selectors
  • :not selector
  • + sibling selector.

Here are a few example cases where the input that is not a child of a subordinate .section div is picked out of a parent with a specific ID, which also has the .section class.

#section1 div + div + div > input {
  border: 2px solid red;
}

#section4 div + div:not(:last-child) input {
  border: 2px solid blue;
}

#section7 > div:first-child input {
  border: 2px solid gold;
}


/* appearance only */

#section4, #section7 {
  margin-top: 10xp;
  border-top: 2px solid gray;
}
<div class="section" id="section1">
  <div>
    <div class="section" id="section2">
      <input type="text" class="input1">
      <input type="text">
    </div>
  </div>
  <div>
    <div>
      <div class="section" id="section3">
        <input type="text">
        <div>more stuff...</div>
      </div>
    </div>
  </div>
  <div>
    <input type="text" class="input1">
    <div>more stuff...</div>
  </div>
</div>

<div class="section" id="section4">
  <div>
    <div class="section" id="section5">
      <input type="text" class="input1">
      <input type="text">
    </div>
  </div>
  <div>
    <input type="text" class="input1">
    <div>more stuff...</div>
  </div>
  <div>
    <div>
      <div class="section" id="section6">
        <input type="text">
        <div>more stuff...</div>
      </div>
    </div>
  </div>
</div>

<div class="section" id="section7">
  <div>
    <input type="text" class="input1">
    <div>more stuff...</div>
  </div>
  <div>
    <div class="section" id="section8">
      <input type="text" class="input1">
      <input type="text">
    </div>
  </div>
  <div>
    <div>
      <div class="section" id="section9">
        <input type="text">
        <div>more stuff...</div>
      </div>
    </div>
  </div>
</div>

The obvious downside here is that you have to do a rule for each input, or at least each pattern you need to match. How annoying this is for you ultimately will depend just how many patterns you have to cover. But it's probably possible one way or another.

cjl750
  • 4,380
  • 3
  • 15
  • 27
  • Unfortunately, my extended HTML also has `div`s that encompass its `input` so it won't be a direct child. I also am not using it for styling so I can't overwrite with a second selector. I need the one selector to uniquely identify the correct element. – MDMazzullo Jun 12 '17 at 23:40
  • Hmm. In that case, I think you will need to post more example code so we can try to work it out. Maybe two or three different scenarios you have to account for, including all distracting wrappers and relevant IDs and classes. Without that, all I can do is guess what might work for you. – cjl750 Jun 12 '17 at 23:54
  • Just edited with a more realistic example. Let me know if that makes it any clearer. It's a confusing situation and I'm having difficulty putting it into words but I think that line that sums it up the best is that I need one selector to uniquely identify any `input` with it's nearest parent `div.section`. – MDMazzullo Jun 13 '17 at 00:02
  • Well that both helps and makes it more confusing. I can't tell any more from the code example which ones are supposed to be styled and which aren't. Can you add some comments to the HTML to indicate the ones you want to select? – cjl750 Jun 13 '17 at 00:07
  • It's the `input.input1`s that I'm looking for that are identical to each other. The other `input`s are distinguishable and therefore easy to find. – MDMazzullo Jun 13 '17 at 00:16
  • Edited my answer; see if it helps. – cjl750 Jun 13 '17 at 00:45
0

The way you formulated your question makes it an impossible problem. As you already know from the other answers, > is the direct child selector.

Since elements nested within #section2 are also nested within #section1, a selector would catch both unless you specify use the direct child selector.

If you cannot make any other assumptions, I don't think there is a way out. You can use nth-child selector at any level of the CSS selector chain if you can find some ordering that places the section that interests you in a specific order relative to the nested one.

Itai
  • 227
  • 3
  • 12
  • Unfortunately, the code is autogenerated by a drag-and-drop tool and makes messy code that comes out differently with each build so those types of things aren't really an option. – MDMazzullo Jun 13 '17 at 00:19
  • Probably not possible then. Consider using it Javascript instead. – Itai Jun 13 '17 at 02:12