ฉันจะป้องกันการสืบทอด CSS ได้อย่างไร


94

ฉันมีเมนูการนำทางแบบลำดับชั้นในแถบด้านข้างที่ใช้รายการที่ซ้อนกัน (แท็ก <ul> และ <li>) ฉันกำลังใช้ธีมที่สร้างไว้ล่วงหน้าซึ่งมีสไตล์สำหรับรายการอยู่แล้ว แต่ฉันต้องการเปลี่ยนสไตล์ของไอเท็มระดับบนสุด แต่ไม่ได้นำไปใช้กับไอเท็มย่อย มีวิธีง่ายๆในการนำสไตล์ไปใช้กับแท็กรายการระดับบนสุดโดยไม่ต้องเรียงซ้อนสไตล์เหล่านั้นลงไปที่รายการย่อยหรือไม่? ฉันเข้าใจว่าฉันสามารถเพิ่มรูปแบบการลบล้างให้กับรายการย่อยได้อย่างชัดเจน แต่ฉันต้องการหลีกเลี่ยงการทำซ้ำโค้ดสไตล์นั้นทั้งหมดหากมีวิธีง่ายๆเพียงแค่พูดว่า "ใช้สไตล์เหล่านี้กับคลาสนี้และอย่าเรียงซ้อน ลงไปที่องค์ประกอบของเด็ก ๆ " นี่คือ html ที่ฉันใช้:

<ul id="sidebar">
  <li class="top-level-nav">
    <span>HEADING 1</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
  <li class="top-level-nav">
    <span>HEADING 2</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
</ul>

ดังนั้น CSS จึงมีสไตล์สำหรับ#sidebar ulและ#sidebar ul liอยู่แล้ว แต่ฉันต้องการเพิ่มสไตล์เพิ่มเติมเพื่อ#sidebar .top-level-navไม่ให้เรียงซ้อนลงไปที่ลูกย่อย มีวิธีใดบ้างในการทำสิ่งนี้ง่ายๆหรือฉันต้องจัดเรียงสไตล์ทั้งหมดใหม่เพื่อให้สไตล์ที่เปิดใช้#sidebar ulอยู่นั้นมีความเฉพาะเจาะจงสำหรับบางคลาส


2
ฉันค้นหาในไซต์เพื่อหาคำถามที่คล้ายกันและไม่พบอะไรเลย (ไม่ได้บอกว่าไม่มี แต่ฉันดูแล้ว) ถ้าคุณรู้ว่ามันคืออะไรคุณช่วยแนะนำฉันได้ไหม ขอบคุณ!

1
stackoverflow.com/questions/747308/breaking-css-inheritance | มันค่อนข้างบอกสิ่งที่แมทธิวตอบ
JasonV

1
ดังนั้นฉันจึงตอบคำตอบคือ "ไม่ไม่มีทางทำได้ง่ายๆ - คุณต้องลบล้างการตั้งค่ารูปแบบทุกรายการในรายการย่อยด้วยตนเอง" - ฉันตีความสิ่งนี้ถูกต้องหรือไม่? ขอบคุณอีกครั้ง.

คำตอบ:


38

ในขณะที่ยังไม่มีตัวเลือกหลัก (หรือตามที่Shaun Inmanเรียกพวกเขาว่าตัวเลือกที่มีคุณสมบัติเหมาะสม ) ดังนั้นคุณจะต้องใช้สไตล์กับไอเท็มรายการรองเพื่อแทนที่สไตล์ในรายการหลัก

Cascading เป็นจุดรวมของ Cascading Style Sheets ดังนั้นชื่อ


13
ข้อมูลนี้ล้าสมัยตั้งแต่ IE8 ดูคำตอบโดย Silviu Postavaru โปรดพิจารณาเพื่อเปลี่ยนเช็คเป็นคำตอบที่เหมาะสมกว่า
tmuecksch

ฮ่า ๆ ฉันยอมรับว่าการเรียงซ้อนเป็นสาระสำคัญ แต่ควรมีวิธีหยุดการขยายพันธุ์จากพ่อแม่พันธุ์เฉพาะที่ตั้งใจให้แตกต่างกัน
Obay Abd-Algader

72

คุณใช้ตัวเลือกลูก

ดังนั้นการใช้

#parent > child

จะทำให้เฉพาะเด็กระดับแรกเท่านั้นที่จะนำรูปแบบไปใช้ น่าเสียดายที่ IE6 ไม่รองรับตัวเลือกลูก

มิฉะนั้นคุณสามารถใช้

#parent child child

หากต้องการกำหนดรูปแบบเฉพาะอื่นให้กับเด็กที่มีระดับต่ำกว่าหนึ่งระดับ


1
คุณช่วยแสดงให้ฉันเห็นใน JSFiddle ได้ไหม ฉันพยายามจัดกึ่งกลางของ div ที่แสดงในบล็อกแบบอินไลน์ แต่มันยังคงเน้นข้อความภายใน div
Calmarius

41

มีคุณสมบัติที่เรียกว่าเป็นallในโมดูล CSS3 มรดก มันทำงานดังนี้:

#sidebar ul li {
  all: initial;
}

ในวันที่ 2016-12 ทุกเบราว์เซอร์ยกเว้น IE / Edge และ Opera Miniรองรับคุณสมบัตินี้


4
@AndriusDobrotinas จะได้รับการสนับสนุนในที่สุด? ดูเหมือนว่าฉันจะเข้าใจความคิดเห็นของคุณไม่ครบถ้วน มีปลั๊กอิน PostCSS ที่ให้คุณสมบัตินี้หากคุณใช้ PostCSS: github.com/maximkoretskiy/postcss-initial
Boldewyn

1
@AndriusDobrotinas ความคิดเห็นของคุณไม่สร้างสรรค์มาก คำตอบถูกโพสต์เพื่อประโยชน์ของชุมชน พยายามอย่างเต็มที่เพื่อดูประโยชน์ของมัน
Cody

2
ณ ตอนนี้มีเพียง IE และ Opera Mini เท่านั้นที่ไม่รองรับเบราว์เซอร์หลักอื่น ๆ ทั้งหมด
Legends

@Boldewyn ไม่มีค่า 'เริ่มต้น' เท่าที่สามารถบอกได้จากเอกสาร w3 ที่เชื่อมโยง ...
benomatis

@webeno มีเมื่อฉันเขียนคำตอบ: w3.org/TR/2013/WD-css3-cascade-20130103/#all-shorthandดูเหมือนว่าจะมีความแตกต่างเล็กน้อยระหว่างเก่าdefaultกับใหม่unsetแต่ตอนนี้ฉัน ' ฉันไม่มีเวลาตรวจสอบเพิ่มเติม อย่าลังเลที่จะแก้ไขคำตอบเพื่อให้เป็นปัจจุบัน
Boldewyn

26

คุณสามารถใช้ตัวเลือก *เพื่อเปลี่ยนสไตล์ลูกกลับเป็นค่าเริ่มต้น

ตัวอย่าง

#parent {
    white-space: pre-wrap;
}

#parent * {
    white-space: initial;
}

1
นั่นเป็นทางออกที่ดีมาก - โดยเฉพาะอย่างยิ่งถ้าคุณไม่รู้จักชั้นเรียนของผู้ปกครอง
BurninLeo

ฉันคิดว่าฉันรู้คำตอบ แต่จะตั้งค่าอินไลน์นี้หรือไม่ <div id="parent" style="white-space:pre-wrap;*white-space:initial;"/>
1.21 กิกะวัตต์

11

การห่อด้วย iframe ทำให้ css หลักล้าสมัย


2
ตลกที่ว่านี้เป็นคำตอบที่ทำเครื่องหมายที่เลวร้ายที่สุดเพราะในทางเทคนิคมันเป็นเพียงวิธีทางกายภาพเพื่อหยุด CSS มรดก ไม่ใช่ว่าฉันกำลังเถียงว่าคุณควรใช้วิธีนี้
davidelrizzo

2
ฉันขอแนะนำว่าอย่าใช้ CSS ทางกายภาพปล่อยไว้ในโลกเสมือนจริงที่มันเป็นอยู่!
michaelward82

การเพิ่มจริงiframeทำให้มองไม่เห็นส่วนประกอบลูกของฉัน ความคิด?
Kevin Ghaboosi

5

คำตอบสั้น ๆ คือไม่ไม่สามารถป้องกันการสืบทอด CSS ได้ คุณสามารถลบล้างได้เฉพาะรูปแบบที่กำหนดไว้ในผู้ปกครองเท่านั้น ดูข้อมูลจำเพาะ:

ทุกองค์ประกอบในเอกสาร HTML จะสืบทอดคุณสมบัติที่สืบทอดได้ทั้งหมดจากพาเรนต์ยกเว้นองค์ประกอบรูท ( html) ซึ่งไม่มีพาเรนต์ - W3C

นอกเหนือจากการลบล้างทรัพย์สินที่สืบทอดมาทุกรายการ นอกจากนี้คุณยังสามารถใช้คำหลักเช่นinitial color: initial;นอกจากนี้ยังสามารถใช้ร่วมกับallเช่นall: initial;จะรีเซ็ตคุณสมบัติทั้งหมดในครั้งเดียว ตัวอย่าง:

.container {
  color: blue;
  font-style: italic;
}
.initial {
  all: initial;
}
<div class="container">
  The quick brown <span class="initial">fox</span> jumps over the lazy dog
</div>

ตารางรองรับบราวเซอร์ตามCan I use ...

  • all (ขณะนี้ยังไม่รองรับทั้ง IE และ Edge แต่อย่างอื่นก็ดี)
  • initial (ขณะนี้ยังไม่มีการสนับสนุนใน IE แต่อย่างอื่นก็ดี)

คุณอาจพบว่ามีประโยชน์โดยใช้ตัวเลือกเด็กโดยตรง>ในบางกรณี ตัวอย่าง:

.list > li {
  border: 1px solid red;
  color: blue;
}
<ul class="list">
  <li>
    <span>HEADING 1</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
  <li>
    <span>HEADING 2</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
</ul>

รูปแบบเส้นขอบถูกนำไปใช้กับลูกโดยตรง<li>เท่านั้นเนื่องจากborderเป็นคุณสมบัติที่ไม่สืบทอด แต่สีข้อความถูกนำไปใช้กับเด็กทุกคนเช่นเดียวกับcolorคุณสมบัติที่สืบทอดมา

ดังนั้น>ตัวเลือกจะมีประโยชน์เฉพาะกับคุณสมบัติที่ไม่สืบทอดเท่านั้นเมื่อพูดถึงการป้องกันการสืบทอด


2

คุณสามารถใช้ jQuery เพื่อ "ปิด" พฤติกรรมนี้ได้แม้ว่าฉันแทบจะไม่คิดว่ามันเป็นวิธีแก้ปัญหาที่ดีเพราะคุณได้รับตรรกะการแสดงผลใน css & javascript ถึงกระนั้นขึ้นอยู่กับความต้องการของคุณคุณอาจพบว่ายูทิลิตี้ css ของ jQuery ทำให้ชีวิตคุณง่ายขึ้นกว่าการลองใช้ css แบบแฮ็กกี้โดยเฉพาะอย่างยิ่งถ้าคุณพยายามทำให้มันใช้งานได้กับ IE6


2

ตัวอย่างเช่นถ้าคุณมีสอง div ในเอกสาร XHTML

<div id='div1'>
    <p>hello, how are you?</p>
    <div id='div2'>
        <p>I am fine, thank you.</p>
    </div>
</div>

จากนั้นลองใช้ใน CSS

#div1 > #div2 > p{
    color: red;
}

มีผลเฉพาะย่อหน้า 'div2'

#div1 > p {
    color: red;
} 

มีผลเฉพาะย่อหน้า 'div1'


2

คุณไม่ต้องการการอ้างอิงคลาสสำหรับlis แทนที่จะมี CSS เช่น

li.top-level-nav { color:black; }

คุณสามารถเขียน

ul#sidebar > li { color:black; }

การดำเนินการนี้จะใช้สไตล์เฉพาะกับlis ที่ลงมาจากแถบด้านข้างulทันที


0

เพียงตั้งค่ากลับเป็นค่าเริ่มต้นในตัวเลือก "#sidebar ul li"


ขอบคุณสำหรับคำตอบ. ใช่ฉันเข้าใจว่าฉันสามารถตั้งค่ากลับเป็นรูปแบบของรายการย่อยได้ แต่ฉันพยายามหลีกเลี่ยงสิ่งนั้นเพราะฉันใช้ธีมที่ไม่ได้สร้างและฉันสงสัยว่าจะประหยัดเวลาได้มากไหม โดยใช้กฎ "do-not-cascade: true" หรืออะไรทำนองนั้นแทนที่จะค้นหารูปแบบที่แตกต่างกันทั้งหมดสำหรับ ul's และ li ซึ่งกระจัดกระจายไปทั่วสถานที่แล้วกังวลเกี่ยวกับผลลัพธ์ที่ไม่ได้ตั้งใจในพื้นที่อื่น ๆ ของไซต์ .
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.