วิธีส่งผลกระทบต่อองค์ประกอบอื่น ๆ เมื่อองค์ประกอบหนึ่งถูกโฮเวอร์


459

สิ่งที่ฉันต้องการจะทำคือเมื่อมีบางอย่างจะวนเวียนอยู่ก็ต้องการส่งผลกระทบต่อคุณสมบัติของผู้อื่นdivdiv

ยกตัวอย่างเช่นในนี้สาธิต JSFiddleเมื่อคุณวางเมาส์เหนือ#cubeจะเปลี่ยนbackground-colorแต่สิ่งที่ฉันต้องการก็คือว่าเมื่อฉันวางเมาส์เหนือ#container, #cubeได้รับผลกระทบ

div {
  outline: 1px solid red;
}
#container {
  width: 200px;
  height: 30px;
}
#cube {
  width: 30px;
  height: 100%;
  background-color: red;
}
#cube:hover {
  width: 30px;
  height: 100%;
  background-color: blue;
}
<div id="container">

  <div id="cube">
  </div>

</div>

คำตอบ:


984

หากลูกบาศก์อยู่ภายในคอนเทนเนอร์โดยตรง:

#container:hover > #cube { background-color: yellow; }

หาก cube อยู่ถัดจาก (หลังจากแท็กปิดคอนเทนเนอร์) คอนเทนเนอร์:

#container:hover + #cube { background-color: yellow; }

หากลูกบาศก์อยู่ภายในภาชนะ:

#container:hover #cube { background-color: yellow; }

หากคิวบ์เป็นพี่น้องของคอนเทนเนอร์:

#container:hover ~ #cube { background-color: yellow; }

107
อย่าลืม combinator พี่น้องทั่วไป~สำหรับ 'คิวบ์อยู่ที่ไหนสักแห่งหลังจากภาชนะใน DOM และแบ่งปันผู้ปกครอง'
robertc

3
มันเท่ห์มาก มีแหล่งข้อมูลที่ฉันสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ไหม? เบราว์เซอร์ทั้งหมดรองรับ CSS3 หรือไม่ คงจะดีถ้ามีข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนั้น ขอบคุณมาก!
ไม่ระบุชื่อ

2
+1 คำตอบยอดเยี่ยม @Mike เกิดอะไรขึ้นถ้า#containerอยู่ถัดจาก#cubeคือ#containerดังต่อไปนี้#cube?
PeterKA

4
จะทำอย่างไรถ้าองค์ประกอบที่โฮเวอร์อยู่ภายในคอนเทนเนอร์ (ซึ่งเราต้องการให้มีผลกระทบ) ??? ตัวอย่างเช่น: #cube: hover #container {เอฟเฟกต์ CSS บางอย่าง)
Hanzallah Afgan

2
คำตอบที่ดี !! จะเป็นอย่างไรถ้าฉันต้องการเปลี่ยนผู้ปกครองเมื่อฉันเลื่อนลูก ฉันคิดว่าไม่มีตัวเลือกสำหรับสิ่งนั้น
มิเคล

41

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

#container:hover #cube {
    background-color: yellow;   
}

ตัวอย่างนี้จะทำงานเฉพาะตั้งแต่เป็นลูกของcube containerสำหรับสถานการณ์ที่ซับซ้อนมากขึ้นคุณต้องใช้ CSS อื่นหรือใช้ JavaScript


35

โดยใช้ตัวเลือกพี่น้องคือการแก้ปัญหาทั่วไปสำหรับการจัดแต่งทรงผมองค์ประกอบอื่น ๆ เมื่อโฉบเหนือที่ได้รับอย่างใดอย่างหนึ่งแต่มันทำงานได้เฉพาะในกรณีที่องค์ประกอบอื่น ๆ ตามที่ได้รับอย่างใดอย่างหนึ่งได้ใน DOM เราจะทำอย่างไรเมื่อองค์ประกอบอื่น ๆ ควรอยู่ก่อนองค์ประกอบที่ลอยอยู่ สมมติว่าเราต้องการใช้วิดเจ็ตการจัดอันดับแถบสัญญาณเหมือนด้านล่าง:

วิดเจ็ตการจัดอันดับแถบสัญญาณ

สามารถทำได้อย่างง่ายดายจริง ๆ โดยใช้รูปแบบ CSS flexbox โดยการตั้งค่าflex-directionเพื่อreverseให้องค์ประกอบจะแสดงในลำดับที่ตรงกันข้ามจากคนที่พวกเขาอยู่ใน DOM ภาพหน้าจอด้านบนนั้นมาจากวิดเจ็ตดังกล่าวซึ่งใช้งานด้วย CSS บริสุทธิ์

Flexbox ได้รับการสนับสนุนเป็นอย่างดีจากเบราว์เซอร์ที่ทันสมัยถึง 95%


สิ่งนี้สามารถแก้ไขได้หรือไม่ไฮไลท์จะไม่หายไปเมื่อเลื่อนเมาส์จากแถบหนึ่งไปยังอีกแถบหนึ่ง? การกระพริบเป็นสิ่งที่ทำให้เสียสมาธิเล็กน้อย
Cerbrus

@Cerbrus: เพิ่มโซลูชันที่ไม่ซ่อนโฮเวอร์เมื่อเมาส์อยู่ระหว่างแท่ง ข้อเสียคือความกว้างของแท่งไม่เท่ากันอีกต่อไป
Dan Dascalescu

1
ลองใช้ในตัวอย่างข้อมูลแรกของคุณ: เปิด.rating div, ลบระยะขอบและเพิ่มborder-right: 4px solid white;
Cerbrus

1
ทิศทางการโค้งงอ (ไม่รองรับ IE) หรือ 1) สีดำเป็นค่าเริ่มต้น 2) สีฟ้าทั้งหมดบนเม้าส์เหนือคอนเทนเนอร์ 3) สีดำสำหรับพี่น้องคนต่อไปที่แถบเลื่อนแถบ :)
Stephane Mathis

ฉันทำซอนี้ (อย่างน้อยสำหรับฉัน) ทำให้เพิ่มขึ้นเล็กน้อยในสิ่งที่เกิดขึ้นที่นี่ jsfiddle.net/maxshuty/cj55y33p/3
maxshuty

8

ขอบคุณมากสำหรับ Mike และ Robertc สำหรับการโพสต์ที่เป็นประโยชน์ของพวกเขา!

หากคุณมีสององค์ประกอบใน HTML ของคุณและคุณต้องการที่จะ:hoverมากกว่าหนึ่งและกำหนดเป้าหมายการเปลี่ยนแปลงสไตล์ในอื่น ๆ ทั้งสององค์ประกอบจะต้องเกี่ยวข้องโดยตรง - ผู้ปกครองเด็กหรือพี่น้อง ซึ่งหมายความว่าองค์ประกอบทั้งสองจะต้องเป็นองค์ประกอบหนึ่งในอีกองค์ประกอบหนึ่งหรือทั้งสองต้องอยู่ในองค์ประกอบที่มีขนาดใหญ่กว่าเดิม

ผมอยากจะแสดงผลคำจำกัดความในช่องทางด้านขวาของเบราว์เซอร์เป็นผู้ใช้ของฉันอ่านผ่านทางเว็บไซต์ของฉันและ:hoverแง่ไฮไลต์มากกว่า; ดังนั้นฉันไม่ต้องการให้องค์ประกอบ 'นิยาม' แสดงในองค์ประกอบ 'ข้อความ'

ฉันเกือบยอมแพ้และเพิ่งเพิ่มจาวาสคริปต์ในหน้าของฉัน แต่นี่คืออนาคตแล้ว! เราไม่ควรที่จะอดทนกับ back sass จาก CSS และ HTML เพื่อบอกเราว่าเราต้องวางองค์ประกอบของเราเพื่อให้ได้เอฟเฟกต์ที่เราต้องการ! ในที่สุดเราก็ยอมจำนน

ในขณะที่องค์ประกอบ HTML จริงในไฟล์จะต้องซ้อนกันหรืออยู่ในองค์ประกอบเดียวเพื่อเป็น:hoverเป้าหมายที่ถูกต้องซึ่งกันและกันpositionคุณลักษณะcss สามารถใช้เพื่อแสดงองค์ประกอบใด ๆ ที่คุณต้องการ ฉันใช้ตำแหน่ง: แก้ไขเพื่อกำหนดเป้าหมายของ:hoverการกระทำของฉันในตำแหน่งที่ฉันต้องการบนหน้าจอของผู้ใช้โดยไม่คำนึงถึงตำแหน่งในเอกสาร HTML

html ที่:

<div id="explainBox" class="explainBox"> /*Common parent*/

  <a class="defP" id="light" href="http://en.wikipedia.or/wiki/Light">Light                            /*highlighted term in text*/
  </a> is as ubiquitous as it is mysterious. /*plain text*/

  <div id="definitions"> /*Container for :hover-displayed definitions*/
    <p class="def" id="light"> /*example definition entry*/ Light:
      <br/>Short Answer: The type of energy you see
    </p>
  </div>

</div>

CSS:

/*read: "when user hovers over #light somewhere inside #explainBox
    set display to inline-block for #light directly inside of #definitions.*/

#explainBox #light:hover~#definitions>#light {
  display: inline-block;
}

.def {
  display: none;
}

#definitions {
  background-color: black;
  position: fixed;
  /*position attribute*/
  top: 5em;
  /*position attribute*/
  right: 2em;
  /*position attribute*/
  width: 20em;
  height: 30em;
  border: 1px solid orange;
  border-radius: 12px;
  padding: 10px;
}

ในตัวอย่างนี้เป้าหมายของการเป็น:hoverคำสั่งจากองค์ประกอบภายใน#explainBoxต้องเป็นหรือยังอยู่ใน#explainBox #explainBoxแอตทริบิวต์ตำแหน่งที่กำหนดให้ #definitions บังคับให้ปรากฏในตำแหน่งที่ต้องการ (นอก#explainBox) แม้ว่าจะอยู่ในตำแหน่งที่ไม่พึงประสงค์ทางเทคนิคภายในเอกสาร HTML

ฉันเข้าใจว่าเป็นรูปแบบที่ไม่ดีที่จะใช้#idองค์ประกอบ HTML มากกว่าหนึ่งองค์ประกอบ อย่างไรก็ตามในกรณีนี้กรณีของ#lightสามารถอธิบายได้อย่างอิสระเนื่องจากตำแหน่งของตนใน#idองค์ประกอบที่ไม่ซ้ำกัน มีเหตุผลที่จะไม่ทำซ้ำid #lightในกรณีนี้หรือไม่?


ค่อนข้างคำตอบยาวสำหรับจุดสั้น ๆ แต่นี่คือ jsfiddle ของมันjsfiddle.net/ubershmekel/bWgq6/1
ubershmekel

1
เบราว์เซอร์บางตัวจะประหลาดเมื่อคุณใช้IDหลายครั้งเหมือนกัน classใช้เพียง
Serj Sagan

6

สิ่งนี้ใช้ได้สำหรับฉันเท่านั้น:

#container:hover .cube { background-color: yellow; }

ที่ไหน.cubeเป็น CssClass #cubeของ

การทดสอบในFirefox , Chromeและขอบ


4

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

สำหรับสิ่งนี้ฉันจะพึ่งพาการใช้คุณสมบัติที่กำหนดเอง (ตัวแปร CSS) ตามที่เราสามารถอ่านได้ในสเปค :

คุณสมบัติที่กำหนดเองเป็นคุณสมบัติทั่วไปดังนั้นจึงสามารถประกาศในองค์ประกอบใด ๆ ได้รับการแก้ไขด้วยการสืบทอดปกติและกฎการเรียงซ้อน ...

แนวคิดคือการกำหนดคุณสมบัติที่กำหนดเองภายในองค์ประกอบหลักและใช้เพื่อกำหนดสไตล์องค์ประกอบลูกและเนื่องจากคุณสมบัติเหล่านี้ได้รับการสืบทอดเราเพียงแค่ต้องเปลี่ยนคุณสมบัติเหล่านี้ภายในองค์ประกอบหลักที่อยู่เหนือโฮเวอร์

นี่คือตัวอย่าง:

#container {
  width: 200px;
  height: 30px;
  border: 1px solid var(--c);
  --c:red;
}
#container:hover {
  --c:blue;
}
#container > div {
  width: 30px;
  height: 100%;
  background-color: var(--c);
}
<div id="container">
  <div>
  </div>
</div>

ทำไมจึงดีกว่าการใช้ตัวเลือกเฉพาะร่วมกับการโฮเวอร์

ฉันสามารถให้เหตุผลอย่างน้อย 2 ข้อที่ทำให้วิธีนี้เป็นวิธีที่ดีในการพิจารณา:

  1. หากเรามีองค์ประกอบซ้อนกันจำนวนมากที่ใช้สไตล์เดียวกันสิ่งนี้จะหลีกเลี่ยงตัวเลือกที่ซับซ้อนในการกำหนดเป้าหมายทั้งหมดในโฮเวอร์ การใช้คุณสมบัติที่กำหนดเองเราเพียงแค่เปลี่ยนค่าเมื่อวางเมาส์บนองค์ประกอบหลัก
  2. คุณสมบัติที่กำหนดเองสามารถใช้เพื่อแทนที่ค่าของคุณสมบัติใด ๆ และยังเป็นค่าบางส่วนของมัน ตัวอย่างเช่นเราสามารถกำหนดคุณสมบัติที่กำหนดเองสำหรับสีและเราใช้ภายในborder , linear-gradient, background-color, box-shadowฯลฯ นี้จะหลีกเลี่ยงเรา reseting คุณสมบัติเหล่านี้ทั้งหมดในโฉบ

นี่คือตัวอย่างที่ซับซ้อนมากขึ้น:

.container {
  --c:red;
  width:400px;
  display:flex;
  border:1px solid var(--c);
  justify-content:space-between;
  padding:5px;
  background:linear-gradient(var(--c),var(--c)) 0 50%/100% 3px no-repeat;
}
.box {
  width:30%;
  background:var(--c);
  box-shadow:0px 0px 5px var(--c);
  position:relative;
}
.box:before {
  content:"A";
  display:block;
  width:15px;
  margin:0 auto;
  height:100%;
  color:var(--c);
  background:#fff;
}

/*Hover*/
.container:hover {
  --c:blue;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
</div>

ดังที่เราเห็นด้านบนเราต้องการการประกาศ CSSเพียงครั้งเดียวเพื่อเปลี่ยนคุณสมบัติมากมายขององค์ประกอบที่แตกต่างกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.