2

I've been using an ID plus descendants style rule to give all descendants of a div no padding and no margin. But I noticed that it's more specific than the styles in ID selector.

I have multiple divs. Is there a way to make it less specific?

In the example below the padding and border is not applied because the ID+* is more specific:

#list1item1 {
  padding-left: 10px;
  outline: 1px dashed green;
}

#list2item1 {
  padding-left: 20px;
  outline: 1px dashed blue;
}

#GroceryList1 {
  left: 40px;
  top: 20px;
  position: absolute;
}

#GroceryList2 {
  left: 200px;
  top: 20px;
  position: absolute;
}

#GroceryList1 * {
  margin: 0;
  padding: 0;
  outline: none;
}

#GroceryList2 * {
  margin: 0;
  padding: 0;
  outline: none;
}
<div id="GroceryList1">
   <ol>
      <li id="list1item1">Bread
      <li>Stick of Butter
      <li>Gallon of milk
   </ol>
</div>

<div id="GroceryList2">
   <ol>
      <li id="list2item1">Bread
      <li>Stick of Butter
      <li>Gallon of milk
   </ol>
</div>

Without switching to classes is there a way to select all descendants of a div where a regular ID selector is more specific?

1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231
  • Try to use classes? – Mark Schultheiss Jul 01 '19 at 23:06
  • @MarkSchultheiss It's for a unique use case and I want to know it's possible for knowings sake. ;) – 1.21 gigawatts Jul 01 '19 at 23:13
  • 1
    I understand that, my comment was more of a general statement as I have noticed when an ID is used in CSS things often get complex to maintain etc. Not a bad question, and my comment was simply that, a comment regarding the generalities in this regard. I did up vote the question as I did think it adds to the general knowledge base. – Mark Schultheiss Jul 01 '19 at 23:17
  • @MarkSchultheiss With ID's it does get more complex and it can break easier. But in my case I have a ID dictionary. So I can manage it and create new ID's at will. I can also switch to classes but that adds some complexity that have to prioritize for now. – 1.21 gigawatts Jul 02 '19 at 01:13

2 Answers2

3

You could use an attribute selector beginning with the GroceryList string (but not the number after the string).

[id^=GroceryList] * {
  margin: 0;
  padding: 0;
  outline: none;
}

This would not override the more specific padding rules you've defined.

#list1item1 {
  padding-left: 10px;
  outline: 1px dashed green;
}

#list2item1 {
  padding-left: 20px;
  outline: 1px dashed blue;
}

#GroceryList1 {
  left: 40px;
  top: 20px;
  position: absolute;
}

#GroceryList2 {
  left: 200px;
  top: 20px;
  position: absolute;
}

[id^=GroceryList] * {
  margin: 0;
  padding: 0;
  outline: none;
}
<div id="GroceryList1">
   <ol>
      <li id="list1item1">Bread
      <li>Stick of Butter
      <li>Gallon of milk
   </ol>
</div>

<div id="GroceryList2">
   <ol>
      <li id="list2item1">Bread
      <li>Stick of Butter
      <li>Gallon of milk
   </ol>
</div>
Andy Hoffman
  • 18,436
  • 4
  • 42
  • 61
  • Agreed! And this (the way you have it): `[id^=GroceryList]` is better than this (the way I have it): `div[id^=GroceryList]` IMO :) – Frish Jul 01 '19 at 22:43
  • @Frish Yah, since `id`s must be unique, including the selector in front of the rule seems superfluous. – Andy Hoffman Jul 01 '19 at 22:46
  • The [id^=GroceryList] * is to match a value starting with `GroceryList` so that it matches both correct? If I wanted to target each `div` specifically I would use `[id=GroceryList1] *` and `[id=GroceryList2] *` correct? – 1.21 gigawatts Jul 01 '19 at 23:12
  • 1
    @1.21gigawatts Everything in your comment is correct. – Andy Hoffman Jul 01 '19 at 23:13
1
  1. Wildcard selector: [id^="GroceryList"]

  2. first-of-type selctor: li:first-of-type

All together now!

#GroceryList1 {
  left: 40px;
  top: 20px;
  position: absolute;
}

#GroceryList2 {
  left: 200px;
  top: 20px;
  position: absolute;
}

/* now overridden by below selector */
[id^="GroceryList"] * {
  margin: 0;
  padding: 0;
  outline: none;
}

[id^="GroceryList"] ol li:first-of-type {
  padding-left: 10px;
  outline: 1px dashed green;
}

/* override rule above */
#list2item1 {
  padding-left: 20px;
  outline: 1px dashed blue;
}
<div id="GroceryList1">
   <ol>
      <li id="list1item1">Bread
      <li>Stick of Butter
      <li>Gallon of milk
   </ol>
</div>

<div id="GroceryList2">
   <ol>
      <li id="list2item1">Bread
      <li>Stick of Butter
      <li>Gallon of milk
   </ol>
</div>

With help from this SO: wildcard * in CSS for classes

Frish
  • 1,371
  • 10
  • 20
  • What reason do you use the first of type selector? – 1.21 gigawatts Jul 01 '19 at 23:07
  • 1
    If the pattern of ids on the first list element of Grocery list persists, then you can use `first-of-type` so you don't have to style the ids. If you ever have something like `id="list3item2"`, then of course this will not work. You could then use `nth-of-type`! – Frish Jul 02 '19 at 02:42