Apakah ada pemilih "saudara sebelumnya"?

1356

Tanda tambah ( +) adalah untuk saudara kandung berikutnya.

Apakah ada yang setara untuk saudara sebelumnya?

Jourkey
sumber
18
OMG, semua jawaban di sini menyarankan Anda membalik urutan elemen html dan kemudian menggunakan CSS untuk membuatnya tampak terbelakang adalah peregangan yang nyata. Tentu itu tidak menentukan dalam pertanyaan, tetapi sebagian besar pertanyaan "Anda dapat melakukan X dengan CSS" seharusnya mengasumsikan Anda tidak dapat mengubah HTML secara struktural.
squarecandy
3
@ quarecandy, saya sebagian besar setuju dengan komentar Anda. Tetapi solusi yang Anda rujuk sebagai tidak memadai tetap berguna dalam beberapa kasus (perhatikan upvotes). Jadi mereka layak diposkan. Apa yang Anda lihat sebagai "bentangan nyata" dapat menjadi "solusi kreatif" bagi orang lain.
Michael Benjamin

Jawaban:

839

Tidak, tidak ada pemilih "saudara sebelumnya".

Pada catatan terkait, ~untuk saudara pengganti umum (artinya elemen datang setelah yang satu ini, tetapi tidak harus segera setelah itu) dan merupakan pemilih CSS3. +untuk saudara berikutnya dan CSS2.1.

Lihat Combinator Saudara Adjacent dari Selectors Level 3 dan 5.7 Selector Adjacent Adjacent dari Cascading Style Sheets Level 2 Revisi 1 (CSS 2.1) Spesifikasi .

cletus
sumber
14
Dari standar CSS3: Elemen-elemen yang diwakili oleh dua urutan berbagi induk yang sama di pohon dokumen dan elemen yang diwakili oleh urutan pertama mendahului (tidak harus segera) elemen diwakili oleh yang kedua.
Lie Ryan
26
@Lie Ryan: Ya, tapi point cletus yang membuat jawabannya adalah bahwa Anda tidak memilih elemen sebelumnya.
BoltClock
42
Inilah contoh yang saya buat untuk melihat apa yang bisa dan tidak bisa dilakukan. jsfiddle.net/NuuHy/1
Abacus
7
Fungsi jquery yang berguna untuk ini adalah prev (). Misalnya $ ("# the_element"). Prev (). Css ("background-color", "red")
Satbir Kira
1
Tergantung pada markup Anda, ini mungkin membantu: stackoverflow.com/questions/42680881/…
samnau
235

Saya menemukan cara untuk gaya semua saudara sebelumnya (kebalikan dari ~) yang dapat bekerja tergantung pada apa yang Anda butuhkan.

Katakanlah Anda memiliki daftar tautan dan ketika melayang di satu tautan, semua yang sebelumnya akan berubah menjadi merah. Anda bisa melakukannya seperti ini:

/* default link color is blue */
.parent a {
  color: blue;
}

/* prev siblings should be red */
.parent:hover a {
  color: red;
}
.parent a:hover,
.parent a:hover ~ a {
  color: blue;
}
<div class="parent">
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
</div>

mantish
sumber
17
Anda dapat menambahkan penjelasan tentang cara kerjanya. (Tampaknya Anda menerapkan gaya ke semua item dan ke item berikut tetapi dapat dijelaskan secara eksplisit)
AL
1
Solusi yang luar biasa. Tidak perlu menyusun ulang elemen dalam markup atau render (via float:right). Itu memang membutuhkan ruang putih runtuh antara unit / kata dan padding bukan margin, tetapi berfungsi dengan baik sebaliknya!
Steven Vachon
7
ya, tetapi satu sebelumnya diperlukan sebagian besar waktu TIDAK SEMUA yang sebelumnya!
azerafati
42
Tautan semua berubah merah jika saya mengarahkan kursor ke ruang di antara mereka, untuk saya.
Lynn
3
@Lynn jawabannya hanya mencakup kode untuk membuat tautan sebelumnya merah saat di-hover. Gaya tambahan tergantung pada kasus penggunaan Anda. Untuk komponen peringkat bintang (yang saya kira merupakan kasus umum), Anda harus menyingkirkan ruang itu dan juga membuat merah tautan yang melayang-layang.
mantish
164

Selektor level 4 memperkenalkan:has() (sebelumnya indikator subjek !) yang akan memungkinkan Anda memilih saudara sebelumnya dengan:

previous:has(+ next) {}

... tetapi pada saat penulisan, ini agak jauh melampaui batas pendarahan untuk dukungan browser.

Quentin
sumber
52
"Bleeding edge for support browser" mungkin terlalu berlebihan. Saat menulis ini, bahkan Chrome versi terbaru tidak dapat menggunakan :has()pseudo-class.
Reed Martin
33
@ReedMartin - Itu sebabnya saya mengatakan agak jauh dari tepi pendarahan
Quentin
12
": telah tidak ditandai sebagai bagian dari profil pemilih dinamis, yang berarti tidak dapat digunakan dalam stylesheet; hanya dengan fungsi seperti document.querySelector ()." - developer.mozilla.org/en-US/docs/Web/CSS/:has
Arch Linux Tux
1
@ArchLinuxTux: "Keterbatasan ini sekarang dihapus", jadi suatu saat kita mungkin dapat menggunakan fitur ini: D.
Jacob van Lingen
@JacobvanLingen - caniuse.com/#feat=css-has mendukung ada peramban itu saat ini -.
Quentin
153

Pertimbangkan orderproperti tata letak fleksibel dan kisi.

Saya akan fokus pada flexbox pada contoh di bawah ini, tetapi konsep yang sama berlaku untuk Grid.


Dengan flexbox, pemilih saudara sebelumnya dapat disimulasikan.

Secara khusus, orderproperti fleksibel dapat memindahkan elemen di sekitar layar.

Ini sebuah contoh:

Anda ingin elemen A menjadi merah ketika elemen B melayang.

<ul>
    <li>A</li>
    <li>B</li>
</ul>

LANGKAH

  1. Buat ulwadah fleksibel.

    ul { display: flex; }

  1. Balikkan urutan saudara kandung dalam mark-up.

    <ul>
       <li>B</li>
       <li>A</li>
    </ul>

  1. Gunakan pemilih saudara untuk menargetkan Elemen A ( ~atau +akan melakukannya).

    li:hover + li { background-color: red; }

  1. Gunakan orderproperti flex untuk mengembalikan urutan saudara pada tampilan visual.

    li:last-child { order: -1; }

... dan voila! Selector saudara kandung sebelumnya lahir (atau setidaknya disimulasikan).

Berikut kode lengkapnya:

ul {
    display: flex;
}

li:hover + li {
    background-color: red;
}

li:last-child {
    order: -1;
}

/* non-essential decorative styles */
li {
    height: 200px;
    width: 200px;
    background-color: aqua;
    margin: 5px;
    list-style-type: none;
    cursor: pointer;
}
<ul>
    <li>B</li>
    <li>A</li>
</ul>

Dari spec flexbox:

5.4. Urutan Tampilan: orderproperti

Item fleksibel, secara default, ditampilkan dan ditata dalam urutan yang sama seperti yang muncul dalam dokumen sumber. The orderproperti dapat digunakan untuk mengubah urutan ini.

The orderkontrol properti urutan item fleksibel muncul dalam wadah flex, dengan menetapkan mereka untuk kelompok ordinal. Dibutuhkan <integer>nilai tunggal , yang menentukan kelompok ordinal mana item flex milik.

Nilai awal orderuntuk semua item fleksibel adalah 0.

Lihat juga orderdalam spesifikasi Layout Kotak CSS .


Contoh "penyeleksi saudara sebelumnya" dibuat dengan orderproperti flex .

.container { display: flex; }

.box5 { order: 1; }    
.box5:hover + .box4 { background-color: orangered; font-size: 1.5em; }

.box6 { order: -4; }
.box7 { order: -3; }
.box8 { order: -2; }
.box9 { order: -1; }
.box9:hover ~ :not(.box12):nth-child(-1n+5) { background-color: orangered;
                                              font-size: 1.5em; }
.box12 { order: 2; }
.box12:hover ~ :nth-last-child(-1n+2) { background-color: orangered;
                                        font-size: 1.5em; }
.box21 { order: 1; }
.box21:hover ~ .box { background-color: orangered; font-size: 1.5em; }

/* non-essential decorative styles */
.container {
    padding: 5px;
    background-color: #888;
}
.box {
    height: 50px;
    width: 75px;
    margin: 5px;
    background-color: lightgreen;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    cursor: pointer;
}
<p>
Using the flex <code>order</code> property to construct a previous sibling selector
</p>

<div class="container">
    <div class="box box1"><span>1</span></div>
    <div class="box box2"><span>2</span></div>
    <div class="box box3"><span>3</span></div>
    <div class="box box5"><span>HOVER ME</span></div>
    <div class="box box4"><span>4</span></div>
</div>

<br>

<div class="container">
    <div class="box box9"><span>HOVER ME</span></div>
    <div class="box box12"><span>HOVER ME</span></div>
    <div class="box box6"><span>6</span></div>
    <div class="box box7"><span>7</span></div>
    <div class="box box8"><span>8</span></div>
    <div class="box box10"><span>10</span></div>
    <div class="box box11"><span>11</span></div>
</div>

<br>

<div class="container">
    <div class="box box21"><span>HOVER ME</span></div>
    <div class="box box13"><span>13</span></div>
    <div class="box box14"><span>14</span></div>
    <div class="box box15"><span>15</span></div>
    <div class="box box16"><span>16</span></div>
    <div class="box box17"><span>17</span></div>
    <div class="box box18"><span>18</span></div>
    <div class="box box19"><span>19</span></div>
    <div class="box box20"><span>20</span></div>
</div>

jsFiddle


Catatan Samping - Dua Keyakinan Lama tentang CSS

Flexbox menghancurkan keyakinan lama tentang CSS.

Salah satu kepercayaan seperti itu adalah bahwa pemilih saudara kandung sebelumnya tidak mungkin dalam CSS .

Untuk mengatakan kepercayaan ini tersebar luas akan menjadi pernyataan yang meremehkan. Inilah contoh pertanyaan terkait tentang Stack Overflow saja:

Seperti dijelaskan di atas, kepercayaan ini tidak sepenuhnya benar. Pemilih saudara sebelumnya dapat disimulasikan dalam CSS menggunakan orderproperti flex .

The z-indexMyth

Keyakinan lama lainnya adalah bahwa z-indexhanya bekerja pada elemen-elemen yang diposisikan.

Faktanya, versi terbaru dari spec - the W3C Editor's Draft - masih menyatakan ini benar:

9.9.1 Menentukan level tumpukan: z-index properti

z-index

  • Nilai: otomatis | | mewarisi
  • Awal: otomatis
  • Berlaku untuk: elemen yang diposisikan
  • Warisan: no
  • Persentase: Tidak Ada
  • Media: visual
  • Nilai yang dihitung: seperti yang ditentukan

(penekanan ditambahkan)

Namun pada kenyataannya, informasi ini sudah usang dan tidak akurat.

Elemen yang merupakan item fleksibel atau item kisi dapat membuat konteks penumpukan bahkan ketika positionada static.

4.3. Item Z-Pemesanan Flex

Item fleksibel cat persis sama dengan blok inline, kecuali bahwa urutan dokumen yang dimodifikasi pesanan digunakan di tempat pesanan dokumen mentah, dan z-indexnilai-nilai selain automembuat konteks penumpukan bahkan jika positionada static.

5.4. Z-axis Ordering: z-indexproperti

Urutan lukisan item grid persis sama dengan blok inline, kecuali bahwa agar dokumen pesanan-dimodifikasi digunakan di tempat agar dokumen mentah, dan z-indexnilai-nilai selain automenciptakan konteks susun bahkan jika positionini static.

Berikut ini demonstrasi z-indexbekerja pada item fleksibel yang tidak diposisikan: https://jsfiddle.net/m0wddwxs/

Michael Benjamin
sumber
15
The orderproperti bukan solusi karena semata-mata dimaksudkan untuk mengubah visual yang order, sehingga tidak tidak mengembalikan asli semantical agar Anda dipaksa untuk perubahan dalam HTML untuk solusi ini bekerja.
Marat Tanalin
2
@Marat Tanalin: Untuk 90% kasus penggunaan, dengan asumsi dukungan browser tidak menjadi masalah, ini akan berfungsi dengan baik. 10% kasus penggunaan lainnya adalah 1) kasus di mana mengubah urutan visual bukanlah solusi, atau 2) kasus yang tidak melibatkan CSS sama sekali. Untungnya, untuk # 2, penyeleksi-4 menyediakan: has (), dan terserah kepada pengembang perpustakaan pemilih untuk mengimplementasikannya.
BoltClock
5
Perlu diingat bahwa ED CSS2.2 yang Anda kutip, pada dasarnya, masih CSS2. Dan tata letak flexbox dan kisi tidak ada di CSS2, sejauh yang menyangkut CSS2, informasi itu pasti benar. Paling tidak, teks dapat diperbarui untuk menyebutkan bahwa indeks-z dapat berlaku untuk jenis elemen lain di tingkat CSS masa depan, dengan cara yang sama seperti yang dikatakan properti lain dapat membangun konteks susun, seperti opacity.
BoltClock
3
Jika ada yang mengalami kesulitan memahami kapan z-indexakan bekerja, bahkan ketika "omg, tidak ada yang positionditentukan!", Spesifikasi menyebutkan konsep konteks susun , yang dijelaskan dengan baik oleh artikel ini di MDN
Rogier Spieker
3
@Michael_B sama-sama! Saya sudah berurusan dengan banyak front-enders tidak menyadari hal ini. Satu hal lain yang ingin saya sebutkan, pemilih saudara palsu sebelumnya juga bekerja dengan baikfloat: right (atau cara lain untuk membalik urutan, yang flex/ordermemiliki sedikit (paling sedikit?) Efek samping). Mengocok dua biola: mendemonstrasikan float: rightpendekatan , dan mendemonstrasikandirection: rtl
Rogier Spieker
69

Saya memiliki pertanyaan yang sama, tetapi kemudian saya memiliki momen "duh". Alih-alih menulis

x ~ y

menulis

y ~ x

Jelas ini cocok dengan "x" bukan "y", tetapi menjawab "apakah ada kecocokan?" pertanyaan, dan traversal DOM sederhana dapat membuat Anda ke elemen yang tepat lebih efisien daripada perulangan di javascript.

Saya menyadari bahwa pertanyaan awal adalah pertanyaan CSS jadi jawaban ini mungkin sama sekali tidak relevan, tetapi pengguna Javascript lain mungkin tersandung pada pertanyaan melalui pencarian seperti yang saya lakukan.

Bryan Larsen
sumber
18
Saya percaya itu berfungsi ketika Anda dapat ditemukan dengan mudah. Masalahnya adalah jika y hanya dapat ditemukan relatif terhadap x, dan dalam membalikkannya, Anda tidak dapat menemukan y karena Anda harus menemukan x terlebih dahulu. Ini tentu saja mengacu pada pertanyaan tentang y menjadi saudara yang mendahului daripada yang berikutnya, tetapi mungkin juga berlaku untuk y yang menjadi saudara kandung berikutnya.
David
19
Anda bersikap kasar, Harsh. (maaf, tidak bisa menolak.) Intinya adalah bahwa kadang-kadang Anda hanya perlu tahu "apakah Anda ada?". Di lain waktu Anda dapat menggunakan ": sebelum" untuk meletakkan sesuatu di antara dua elemen. Akhirnya, jika Anda harus masuk ke jQuery, menggunakan find ("y ~ x"). Prev () lebih mudah daripada banyak alternatif.
Bryan Larsen
157
Ide pemilih saudara sebelumnya adalah bahwa ia akan memilih elemen sebelumnya. Sayangnya, membalikkannya, seperti dijelaskan di sini, tidak menyediakan fungsi ini.
Zenexer
14
Terima kasih @ Zenexer atas klarifikasi bahwa jawaban ini tidak memberikan solusi aktual untuk pertanyaan awal, saya mulai merasa diri saya bodoh memikirkan bagaimana y ~ xbisa menyelesaikan masalah saya
Jaime Hablutzel
4
Saya mengerti ide di balik jawaban ini, namun alasan yang diberikan dalam jawaban itu tidak masuk akal. Pemilih y ~ xtidak menjawab "apakah ada kecocokan?" pertanyaan, karena dua penyeleksi yang diberikan di sini berarti hal yang sama sekali berbeda. Tidak ada cara yang y ~ xbisa menghasilkan kecocokan mengingat subtree <root><x/><y/></root>misalnya. Jika pertanyaannya adalah "apakah Anda ada?" maka pemilihnya sederhana saja y. Jika pertanyaannya adalah "apakah Anda ada diberikan saudara x dalam posisi sewenang-wenang?" maka Anda akan membutuhkan kedua penyeleksi. (Meskipun mungkin aku hanya nitpicking pada saat ini ...)
BoltClock
25

Dua trik . Pada dasarnya membalikkan urutan HTML elemen yang Anda inginkan dalam HTML dan menggunakan
~ operator saudara kandung berikutnya :

float-right + membalik urutan elemen HTML

div{ /* Do with the parent whatever you know just to make the
  inner float-right elements appear where desired */
  display:inline-block;
}
span{
  float:right;  /* float-right the elements! */
}
span:hover ~ span{ /* On hover target it's "previous";) elements */
  background:red;
} 
<div>
  <!-- Reverse the order of inner elements -->
  <span>5</span>
  <span>4</span>
  <span>3</span>
  <span>2</span>
  <span>1</span>
</div>


Induk dengan direction: rtl;+ terbalik urutan elemen dalam

.inverse{
  direction: rtl;
  display: inline-block; /* inline-block to keep parent at the left of window */
}
span:hover ~ span{ /* On hover target it's "previous";) elements */
  background:gold;
}
Hover one span and see the previous elements being targeted!<br>

<div class="inverse">
  <!-- Reverse the order of inner elements -->
  <span>5</span>
  <span>4</span>
  <span>3</span>
  <span>2</span>
  <span>1</span>
</div>

Roko C. Buljan
sumber
25

+adalah untuk saudara kandung berikutnya. Apakah ada yang setara untuk saudara sebelumnya?

Anda dapat menggunakan dua penyeleksi kapak :! dan?

Ada 2 penyeleksi saudara berikutnya dalam CSS konvensional:

  • +adalah yang langsung pemilih saudara berikutnya
  • ~adalah setiap pemilih saudara berikutnya

Dalam CSS konvensional, tidak ada pemilih saudara sebelumnya .

Namun, di pustaka pasca-prosesor kapak CSS, ada 2 penyeleksi saudara sebelumnya :

  • ?adalah pemilih saudara langsung sebelumnya (kebalikan dari+ )
  • !adalah setiap pemilih saudara sebelumnya (kebalikan dari ~)

Contoh kerja:

Dalam contoh di bawah ini:

  • .any-subsequent:hover ~ div memilih yang selanjutnya div
  • .immediate-subsequent:hover + div memilih yang selanjutnya langsung div
  • .any-previous:hover ! div memilih yang sebelumnya div
  • .immediate-previous:hover ? div memilih yang sebelumnya langsung div

div {
  display: inline-block;
  width: 60px;
  height: 100px;
  color: rgb(255, 255, 255);
  background-color: rgb(255, 0, 0);
  text-align: center;
  vertical-align: top;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.6s ease-out;
}

code {
  display: block;
  margin: 4px;
  font-size: 24px;
  line-height: 24px;
  background-color: rgba(0, 0, 0, 0.5);
}

div:nth-of-type(-n+4) {
  background-color: rgb(0, 0, 255);
}

div:nth-of-type(n+3):nth-of-type(-n+6) {
  opacity: 1;
}

.any-subsequent:hover ~ div,
.immediate-subsequent:hover + div,
.any-previous:hover ! div,
.immediate-previous:hover ? div {
  opacity: 1;
}
<h2>Hover over any of the blocks below</h2>

<div></div>
<div></div>

<div class="immediate-previous">Hover for <code>?</code> selector</div>
<div class="any-previous">Hover for <code>!</code> selector</div>
<div class="any-subsequent">Hover for <code>~</code> selector</div>
<div class="immediate-subsequent">Hover for <code>+</code> selector</div>

<div></div>
<div></div>

<script src="https://rouninmedia.github.io/axe/axe.js"></script>

Rounin
sumber
3
Ini memberi saya kesalahan sintaks ketika saya mencoba menerapkannya di sass di dalam proyek rel.
alex
25
kapak adalah post-prosesor CSS. Itu tidak menggunakan sintaksis yang sama seperti pra-prosesor CSS seperti Sass, Less atau Stylus.
Rounin
1
@Rounin maukah Anda menambahkan beberapa tautan dokumentasi? Saya tidak dapat menemukan kapak post-prosesor.
Dionys
@Dionys - Terima kasih atas minat Anda. kapak adalah proyek yang saya mulai pada akhir 2016, ketika saya tidak tahu ES2015 dan bahkan objek di JS sangat baru bagi saya. Repositori GitHub ada di sini: github.com/RouninMedia/axe . Saya sangat ingin kembali ke ini di beberapa titik (saya juga telah mengembangkan sesuatu yang disebut kapak-bilah yang setara dengan peristiwa javascript CSS), tapi saya harus menyelesaikan pekerjaan saya pada proyek lain (kode nama ashiva ) terlebih dahulu.
Rounin
17

Solusi flexbox lainnya

Anda dapat menggunakan urutan elemen terbalik dalam HTML. Kemudian selain menggunakan orderseperti pada jawaban Michael_B Anda dapat menggunakan flex-direction: row-reverse;atau flex-direction: column-reverse;tergantung pada tata letak Anda.

Sampel kerja:

.flex {
  display: flex;
  flex-direction: row-reverse;
   /* Align content at the "reversed" end i.e. beginning */
  justify-content: flex-end;
}

/* On hover target its "previous" elements */
.flex-item:hover ~ .flex-item {
  background-color: lime;
}

/* styles just for demo */
.flex-item {
  background-color: orange;
  color: white;
  padding: 20px;
  font-size: 3rem;
  border-radius: 50%;
}
<div class="flex">
  <div class="flex-item">5</div>
  <div class="flex-item">4</div>
  <div class="flex-item">3</div>
  <div class="flex-item">2</div>
  <div class="flex-item">1</div>
</div>

Vadim Ovchinnikov
sumber
16

Tidak ada cara resmi untuk melakukan itu saat ini tetapi Anda dapat menggunakan sedikit trik untuk mencapai ini! Ingat bahwa ini eksperimental dan memiliki beberapa batasan ... (periksa tautan ini jika Anda khawatir tentang kompatibilitas navigator)

Yang bisa Anda lakukan adalah menggunakan pemilih CSS3: pseudo classe dipanggil nth-child()

#list>* {
  display: inline-block;
  padding: 20px 28px;
  margin-right: 5px;
  border: 1px solid #bbb;
  background: #ddd;
  color: #444;
  margin: 0.4em 0;
}

#list :nth-child(-n+4) {
  color: #600b90;
  border: 1px dashed red;
  background: orange;
}
<p>The oranges elements are the previous sibling li selected using li:nth-child(-n+4)</p>

<div id="list">
  <span>1</span><!-- this will be selected -->
  <p>2</p><!-- this will be selected -->
  <p>3</p><!-- this will be selected -->
  <div>4</div><!-- this will be selected -->
  <div>5</div>
  <p>6</p>
  <p>7</p>
  <p>8</p>
  <p>9</p>
</div>

Keterbatasan

  • Anda tidak dapat memilih elemen sebelumnya berdasarkan kelas elemen berikutnya
  • Ini sama untuk kelas semu
0x1gene
sumber
1
@Ian karena :nth-child(-n+4)kelas pseudo yang perlu diterapkan ke pemilih agar berfungsi dengan benar. Jika Anda tidak yakin, cobalah untuk bereksperimen menggunakan garpu biola saya dan Anda akan melihat bahwa itu tidak wajan
0x1gene
1
Sebenarnya, Anda bisa pergi tipe-independen menggunakan *pemilih, tapi itu praktik buruk.
Josh Burgess
1
Ini adalah jawaban yang berfungsi untuk saya, tidak yakin mengapa itu tidak dipilih atau diterima.
Jake Cattrall
1
Sebenarnya, ini berfungsi untuk node yang berbeda: jsfiddle.net/aLhv9r1w/316 . Harap perbarui jawaban Anda :)
Jamie Barker
1
Saya memiliki pemilih yang kompleks, tetapi katakanlah itu li#someListItemdan saya ingin simpul yang tepat sebelum itu (yang bagaimana saya mengartikan "sebelumnya") - Saya tidak melihat bagaimana informasi yang Anda berikan dapat membantu saya mengungkapkannya melalui CSS. Anda hanya memilih n saudara pertama, dan anggap saya tahu n. Berdasarkan logika ini, pemilih dapat melakukan trik dan memilih elemen yang saya butuhkan (seperti: tidak ()).
bitoolean
4

Jika Anda tahu posisi pasti dan :nth-child()pengecualian berbasis semua saudara berikut akan bekerja.

ul li:not(:nth-child(n+3))

Yang akan memilih semua lis sebelum tanggal 3 (mis. 1 dan 2). Tapi, menurut saya ini terlihat jelek dan memiliki usecase yang sangat ketat.

Anda juga dapat memilih anak ke-kanan-ke-kiri:

ul li:nth-child(-n+2)

Yang melakukan hal yang sama.

inti
sumber
3

Tidak. Itu tidak mungkin melalui CSS. Dibutuhkan "Cascade" di hati ;-).


Namun, jika Anda dapat menambahkan JavaScript ke halaman Anda, sedikit jQuery dapat membawa Anda ke tujuan akhir Anda.
Anda dapat menggunakan jQuery's finduntuk melakukan "pandangan ke depan" pada elemen target / kelas / id Anda, lalu mundur untuk memilih target Anda.
Kemudian Anda menggunakan jQuery untuk menulis ulang DOM (CSS) untuk elemen Anda.

Berdasarkan jawaban ini oleh Mike Brant , cuplikan jQuery berikut dapat membantu.

$('p + ul').prev('p')

Ini pertama memilih semua <ul>yang segera mengikuti a <p>.
Lalu "backtracks" untuk memilih semua sebelumnya <p>dari set <ul>s.

Secara efektif, "saudara sebelumnya" telah dipilih melalui jQuery.
Sekarang, gunakan .cssfungsi untuk meneruskan nilai baru CSS Anda untuk elemen itu.


Dalam kasus saya, saya sedang mencari cara untuk memilih DIV dengan id #full-width, tetapi HANYA jika memiliki DIV turunan (tidak langsung) dengan kelas .companies.

Saya memiliki kendali atas semua HTML di bawah .companies, tetapi tidak dapat mengubah HTML apa pun di atasnya.
Dan kaskade hanya berjalan 1 arah: turun.

Jadi saya bisa memilih SEMUA #full-widths.
Atau saya bisa memilih .companiesyang hanya mengikuti a #full-width.
Tetapi saya tidak dapat memilih hanya #full-widths yang melanjutkan .companies .

Dan, sekali lagi, saya tidak dapat menambahkan .companies lebih tinggi di HTML. Bagian HTML itu ditulis secara eksternal, dan dibungkus dengan kode kami.

Tetapi dengan jQuery, saya dapat memilih yang diperlukan #full-width, kemudian menetapkan gaya yang sesuai:

$("#full-width").find(".companies").parents("#full-width").css( "width", "300px" );

Ini menemukan semua #full-width .companies, dan memilih hanya itu .companies, mirip dengan bagaimana penyeleksi digunakan untuk menargetkan elemen tertentu dalam standar di CSS.
Kemudian ia digunakan .parentsuntuk "mundur" dan memilih SEMUA orang tua dari .companies,
tetapi memfilter hasil tersebut untuk menjaga hanya #fill-widthelemen, sehingga pada akhirnya,
itu hanya memilih #full-widthelemen jika memiliki .companiesturunan kelas.
Akhirnya, ia memberikan nilai CSS ( width) baru ke elemen yang dihasilkan.

$(".parent").find(".change-parent").parents(".parent").css( "background-color", "darkred");
div {
  background-color: lightblue;
  width: 120px;
  height: 40px;
  border: 1px solid gray;
  padding: 5px;
}
.wrapper {
  background-color: blue;
  width: 250px;
  height: 165px;
}
.parent {
  background-color: green;
  width: 200px;
  height: 70px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<div class="wrapper">

  <div class="parent">
    "parent" turns red
    <div class="change-parent">
    descendant: "change-parent"
    </div>
  </div>
  
  <div class="parent">
    "parent" stays green
    <div class="nope">
    descendant: "nope"
    </div>
  </div>
  
</div>
Target <b>"<span style="color:darkgreen">parent</span>"</b> to turn <span style="color:red">red</span>.<br>
<b>Only</b> if it <b>has</b> a descendant of "change-parent".<br>
<br>
(reverse cascade, look ahead, parent un-descendant)
</html>

Dokumen Referensi jQuery:
$ () atau jQuery () : elemen DOM.
. find : Dapatkan turunan dari setiap elemen dalam set elemen yang cocok saat ini, difilter oleh pemilih, objek jQuery, atau elemen.
. orangtua : Dapatkan saudara kandung yang sebelumnya mendahului setiap unsur dalam rangkaian unsur yang cocok. Jika pemilih disediakan, ia hanya mengambil saudara sebelumnya jika cocok dengan pemilih itu (memfilter hasilnya hanya menyertakan elemen / pemilih yang terdaftar).
. css : Tetapkan satu atau lebih properti CSS untuk set elemen yang cocok.

SherylHohman
sumber
Ini tidak ada hubungannya dengan pertanyaan. Tentu saja mungkin menggunakan JS dan Anda bahkan tidak perlu jQuery untuk ini ( previousElementSibling).
Fabian von Ellerts
1
@FabianvonEllerts Saya menjawab pertanyaan OP langsung di baris pertama dari tanggapan saya. Sebagai jawaban saya menyatakan, itu secara harfiah tidak mungkin melalui CSS . Saya kemudian memberikan 1 kemungkinan jalur maju untuk mencapai tujuan, menggunakan teknologi (JS | JQuery) yang mungkin akrab bagi pengguna CSS dan memiliki akses. Misalnya, banyak situs WordPress juga memiliki JQuery, jadi ini adalah titik masuk yang mudah: mudah digunakan, diingat, dan dikembangkan. Tidak bertanggung jawab untuk hanya menjawab TIDAK , tanpa memberikan cara alternatif untuk mencapai tujuan. Saya membagikan apa yang saya pelajari dan gunakan ketika saya memiliki pertanyaan yang sama.
SherylHohman
previousElementSibling()bagi mereka yang lebih akrab dengan fungsi asli JS DOM bisa memberikan lain jalur non-CSS ke depan.
SherylHohman
Saya menemukan HACKS CSS lainnya sangat menarik, tetapi untuk kasus penggunaan khusus saya mereka tidak berfungsi (termasuk dalam kategori peringatan), atau terlalu berbelit-belit. Bagi yang lain yang berada dalam keadaan yang sama, adalah adil untuk berbagi metode yang mudah digunakan ini yang dapat bekerja, di mana solusi di atas gagal, atau akan terlalu sulit untuk diterapkan / dipelihara. Banyak HACKS CSS dibagikan. Pekerjaan di sekitar ini tidak dicakup. TIDAK ADA jawaban yang menggunakan +pemilih (tidak ada) yang diminta OP secara khusus. Pertimbangkan jawaban ini sebagai "retasan" JS. Ini di sini untuk menghemat waktu orang lain yang saya habiskan untuk menemukan solusi.
SherylHohman
2

Sayangnya tidak ada pemilih saudara "sebelumnya", tetapi Anda mungkin masih bisa mendapatkan efek yang sama dengan menggunakan pemosisian (mis. Float right). Itu tergantung pada apa yang Anda coba lakukan.

Dalam kasus saya, saya terutama menginginkan sistem peringkat bintang 5 CSS. Saya perlu mewarnai (atau menukar ikon) bintang-bintang sebelumnya. Dengan mengapung setiap elemen dengan benar, pada dasarnya saya mendapatkan efek yang sama (html untuk bintang-bintang karenanya harus ditulis 'mundur').

Saya menggunakan FontAwesome dalam contoh ini dan bertukar antara unicodes fa-star-o dan fa-star http://fortawesome.github.io/Font-Awesome/

CSS:

.fa {
    display: inline-block;
    font-family: FontAwesome;
    font-style: normal;
    font-weight: normal;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* set all stars to 'empty star' */
.stars-container {
    display: inline-block;      
}   

/* set all stars to 'empty star' */
.stars-container .star {
    float: right;
    display: inline-block;
    padding: 2px;
    color: orange;
    cursor: pointer;

}

.stars-container .star:before {
    content: "\f006"; /* fontAwesome empty star code */
}

/* set hovered star to 'filled star' */
.star:hover:before{
    content: "\f005"; /* fontAwesome filled star code */
}

/* set all stars after hovered to'filled star' 
** it will appear that it selects all after due to positioning */
.star:hover ~ .star:before {
    content: "\f005"; /* fontAwesome filled star code */
}

HTML: (40)

JSFiddle: http://jsfiddle.net/andrewleyva/88j0105g/

Andrew Leyva
sumber
1
mengapung tepat dan +atau ~penyeleksi memukul saya sebagai pekerjaan paling bersih di sekitar.
Wylliam Judd
2

Bergantung pada tujuan pasti Anda, ada cara untuk mencapai kegunaan pemilih orang tua tanpa menggunakan satu (bahkan jika ada) ...

Katakanlah kita memiliki:

<div>
  <ul>
    <li><a>Pants</a></li>
    <li><a>Socks</a></li>
    <ul>
      <li><a>White socks</a></li>
      <li><a>Blue socks</a></li>
    </ul>
  </ul>
</div>

Apa yang bisa kita lakukan untuk membuat blok Socks (termasuk warna kaus kaki) menonjol secara visual menggunakan spasi?

Apa yang baik tetapi tidak ada:

ul li ul:parent {
  margin-top: 15px;
  margin-bottom: 15px;
}

Apa yang ada:

li > a {
  margin-top: 15px;
  display: block;
}
li > a:only-child {
  margin-top: 0px;
}

Ini menetapkan semua tautan jangkar untuk memiliki margin 15px di bagian atas dan mengembalikannya kembali ke 0 untuk mereka yang tidak memiliki elemen UL (atau tag lain) di dalam LI.

DynamicDan
sumber
2

Saya membutuhkan solusi untuk memilih saudara kandung sebelumnya. Saya datang dengan solusi ini menggunakan komponen React dan Styled. Ini bukan solusi tepat saya (Ini dari memori, beberapa jam kemudian). Saya tahu ada cacat pada fungsi setHighlighterRow.

OnMouseOver baris akan mengatur indeks baris untuk menyatakan, dan rerender baris sebelumnya dengan warna latar belakang baru

class ReactClass extends Component {
  constructor() {
    this.state = {
       highlightRowIndex: null
    }
  }

  setHighlightedRow = (index) => {
    const highlightRowIndex = index === null ? null : index - 1;
    this.setState({highlightRowIndex});
  }

  render() {
    return (
       <Table>
        <Tbody>
           {arr.map((row, index) => {
                const isHighlighted = index === this.state.highlightRowIndex
                return {
                    <Trow 
                        isHighlighted={isHighlighted}
                        onMouseOver={() => this.setHighlightedRow(index)}
                        onMouseOut={() => this.setHighlightedRow(null)}
                        >
                        ...
                    </Trow>
                }
           })}  
        </Tbody>   
       </Table>
    )
  }
}

const Trow = styled.tr`
    & td {
        background-color: ${p => p.isHighlighted ? 'red' : 'white'};
    }

    &:hover {
        background-color: red;
    }
`;
kyle
sumber
0

Tidak ada, dan ada .

Jika Anda harus menempatkan label sebelum input, alih-alih menempatkan label setelah input, simpan label & input di dalam div, dan gaya div sebagai berikut:

.input-box {
  display: flex;
  flex-direction: column-reverse;
}
<div class="input-box">
                <input
                  id="email"
                  class="form-item"
                 
                />
                <label for="email" class="form-item-header">                  
                      E-Mail*                  
                </label>
</div>

Sekarang Anda dapat menerapkan opsi penataan saudara kandung standar berikutnya yang tersedia di css, dan itu akan tampak seperti Anda menggunakan penataan saudara kandung sebelumnya.

Ron16
sumber
-1

Saya memiliki masalah yang sama dan menemukan bahwa semua masalah seperti ini dapat diselesaikan sebagai berikut:

  1. beri semua item gaya.
  2. beri gaya pada barang pilihan Anda.
  3. beri item berikutnya gaya menggunakan + atau ~.

dan dengan cara ini Anda akan dapat menata item Anda saat ini, item sebelumnya (semua item diganti dengan item saat ini dan berikutnya) dan item berikutnya.

contoh:

/* all items (will be styled as previous) */
li {
  color: blue;
}

/* the item i want to distinguish */
li.milk {
  color: red;
}

/* next items */
li ~ li  {
  color: green;
}


<ul>
  <li>Tea</li>
  <li class="milk">Milk</li>
  <li>Juice</li>
  <li>others</li>
</ul>

Semoga ini bisa membantu seseorang.

Hejar
sumber
1
pada dasarnya trik yang sama seperti pada jawaban yang lebih lama dari utas yang sama: stackoverflow.com/a/27993987/717732
quetzalcoatl