1

If I change the order of elements in a sub selector it affects an element outside of the class.

Common HTML:

<input type='text'>
<hr>
<table class="mytable">
  <tbody> 
    <tr><td><input type='text'></td></tr>
    <tr><td><input type='text'></td></tr>
    <tr><td><input type='text'></td></tr>
  </tbody>
</table>

This CSS works (jsfiddle):

input {
  margin: 0 0 2em;
}
table.mytable input,select,a {
  margin: 0;
}

The following CSS causes the first input before the table to lose its margin simply by placing <select> first in the sublist of elements (jsfiddle). That is the mytable class is activated (selected) for the first input box when it should not be.

input {
  margin: 0 0 2em;
}
table.mytable select,input,a {
  margin: 0;
}

I tested this in both Chrome and Firefox and they both act the same way. So is this a bug? or Can someone explain what I am missing?

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
arvid
  • 88
  • 4

3 Answers3

4

The first selector:

table.mytable input, select, a

targets the following elements:

  • inputs that are descendants of table.mytable
  • all select elements
  • all anchor elements

table.mytable input uses a descendant combinator (the space) to structure the table / input relationship. It applies margin: 0 only to those particular inputs.

Your second selector:

table.mytable select, input, a 

applies margin: 0 to these elements:

  • select elements that are descendants of table.mytable
  • all input elements
  • all anchor elements

So, your first selector targets a particular group of inputs, while the second selector targets all inputs.

In the first example, the first input rule targets all inputs. But the second input rule overrides the first rule due to higher specificity. The first rule ends up matching all inputs, except those targeted by the second rule.

In the second example, the first and second input rules are targeting the same group (all inputs) and have the same weight in terms of specificity. The second rule wins because it is processed later in the cascade. Because both rules are targeting the same group, the first rule is overridden, thus causing the problem you're having.

To target only the inputs within the table try this:

table.mytable select, 
table.mytable input,
a 
Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
1

The way your CSS is written doesn't work in "sub-sets" as you may have hoped.

By placing select first, you've inadvertently now removed the margin from ALL inputs.

The way you have it now, if I were to break it apart would look like this:

input {
    margin: 0 0 2em;
}

table.mytable input {
    margin: 0;
}

select {
    margin: 0;
}

a {
    margin: 0;
}

To get it to work the way you want, you need to include table.mytable with each of the "subsets" you want after each comma.

input {
     margin: 0 0 2em;
}

table.mytable select,
table.mytable input,
table.mytable a {
    margin: 0;
}
socki03
  • 344
  • 1
  • 8
0

Try this.

input {
  margin: 0 0 2em;
}
table.mytable select, table.mytable input, table.mytable a {
  margin: 0;
}
<input type='text'>
<hr>
<table class="mytable">
  <tbody> 
    <tr><td><input type='text'></td></tr>
    <tr><td><input type='text'></td></tr>
    <tr><td><input type='text'></td></tr>
  </tbody>
</table>
Renzo Gaspary
  • 300
  • 5
  • 19