CSS untuk memecah baris sebelum / sesudah item `inline-block` tertentu

202

Katakanlah saya punya HTML ini:

<h3>Features</h3>
<ul>
    <li><img src="alphaball.png">Smells Good</li>
    <li><img src="alphaball.png">Tastes Great</li>
    <li><img src="alphaball.png">Delicious</li>
    <li><img src="alphaball.png">Wholesome</li>
    <li><img src="alphaball.png">Eats Children</li>
    <li><img src="alphaball.png">Yo' Mama</li>
</ul>

dan CSS ini:

li { text-align:center; display:inline-block; padding:0.1em 1em }
img { width:64px; display:block; margin:0 auto }

Hasilnya bisa dilihat di sini: http://jsfiddle.net/YMN7U/1/

Sekarang bayangkan saya ingin memecah ini menjadi tiga kolom, setara dengan menyuntikkan <br>setelah ketiga <li>. (Sebenarnya melakukan hal itu secara semantik dan sintaksis tidak valid.)

Saya tahu cara memilih yang ketiga <li>dalam CSS, tetapi bagaimana cara memaksa pemecah baris setelahnya? Ini tidak bekerja:

li:nth-child(4):after { content:"xxx"; display:block }

Saya juga tahu bahwa kasus khusus ini dimungkinkan dengan menggunakan floatalih-alih inline-block, tetapi saya tidak tertarik menggunakan solusi float. Saya juga tahu bahwa dengan blok lebar tetap ini dimungkinkan dengan mengatur lebar pada induk ulmenjadi sekitar 3x lebar itu; Saya tidak tertarik dengan solusi ini. Saya juga tahu bahwa saya dapat menggunakan display:table-celljika saya menginginkan kolom yang nyata; Saya tidak tertarik dengan solusi ini. Saya tertarik pada kemungkinan memaksa jeda dalam konten inline.

Sunting : Agar jelas, saya tertarik pada 'teori', bukan solusi untuk masalah tertentu. Bisakah CSS menyuntikkan satu baris di tengah display:inline(-block)?elemen, atau apakah itu mustahil? Jika Anda yakin itu tidak mungkin, itu adalah jawaban yang dapat diterima.

Phrogz
sumber
2
Letakkan tiga pertama dan ketiga tiga dalam dua daftar yang berbeda? Saya berasumsi Anda tidak ingin melakukan ini, tapi saya pikir saya akan membuangnya di sana.
JakeParis
Sepertinya Anda perlu memberi tahu kami apa yang sebenarnya ingin Anda capai di sini sehingga seseorang dapat merekomendasikan metode terbaik. Semua opsi yang Anda kecualikan ada untuk menyelesaikan masalah yang Anda miliki, mengapa diperlukan solusi lain?
Jake
4
@Jake Saya sebenarnya melakukan persis apa yang saya nyatakan: menggunakan daftar elemen semantik dan ingin membungkus setelah yang tertentu. Dalam praktiknya saya mengatur lebar wadah, tetapi ini hanya berfungsi dalam kasus khusus saya karena barang-barang tersebut memiliki lebar yang sama dan saya ingin mereka membungkusnya pada tepi yang konsisten. Ini mungkin tidak selalu terjadi. Apa yang saya "benar-benar coba capai" adalah mempelajari apakah CSS dapat memaksa pemecah garis di tengah aliran inline. Jawaban percaya diri "Ini jelas tidak mungkin" dapat diterima (jika benar).
Phrogz

Jawaban:

302

Saya sudah bisa membuatnya bekerja pada elemen LI inline. Sayangnya, itu tidak berfungsi jika elemen LI adalah inline-block:

Demo langsung: http://jsfiddle.net/dWkdp/

Atau versi catatan tebing:

li { 
     display: inline; 
}
li:nth-child(3):after { 
     content: "\A";
     white-space: pre; 
}
Šime Vidas
sumber
2
Sime, mengapa "\ A" tidak bisa dicetak? Semua yang saya coba dengan :afterselalu mencetak sebagai teks lurus.
JakeParis
12
@JMCCreative Itu karakter ASCII 0x0A, AKA a LF (line feed). Lihat w3.org/TR/CSS2/syndata.html#strings
Phrogz
5
@JMC \Aadalah karakter umpan baris ... ini pelarian
Šime Vidas
3
@JMC Spesifikasi resmi: w3.org/TR/CSS21/syndata.html#strings Sitepoint: reference.sitepoint.com/css/content
Šime Vidas
18
berkomentar di sini karena saya terus kembali ke pertanyaan ini setiap beberapa bulan ... Ini tidak akan berfungsi pada inline-blok karena Anda menambahkan jeda baris dalam sesuatu yang bertindak seperti wadah blok dalam konteks inline. Jika Anda bisa keluar dari konteks dengan menyisipkan baris istirahat antara <li> itu akan berhasil. Malu banget karena ini berguna untuk breakpoints desain responsif. Saya kira sebagian besar waktu "inline" sama bermanfaatnya dengan inline-block untuk daftar
user1010892
21

Anda tidak tertarik pada banyak "solusi" untuk masalah Anda. Saya kira tidak ada cara yang baik untuk melakukan apa yang ingin Anda lakukan. Apa pun yang Anda masukkan menggunakan :afterdancontent memiliki validitas sintaksis dan semantik yang persis sama dengan yang akan dilakukan jika Anda baru saja menuliskannya di sana sendiri.

Alat CSS menyediakan pekerjaan. Anda hanya harus mengapung lidan kemudian clear: leftketika Anda ingin memulai baris baru, seperti yang telah Anda sebutkan:

Lihat sebuah contoh: http://jsfiddle.net/marcuswhybrow/YMN7U/5/

Marcus Whybrow
sumber
18
OP tidak tertarik dengan solusi Anda :)
Šime Vidas
2
Yah, tidak ada yang dapat Anda lakukan dengan menggunakan :afterakan valid secara sintaksis atau ide yang baik, karena sudah ada alat di tempat untuk melakukan ini. Karena itu jawabannya.
Marcus Whybrow
32
Salah satu alasan untuk tidak menggunakan pelampung adalah karena tidak ada yang namanya float: center.
kelopak mata
7
ditambah inline-block memungkinkan semua jenis perataan vertikal yang mengapung tidak bisa
user1010892
20
"Apa pun yang Anda masukkan menggunakan: setelah dan konten memiliki sintaksis dan semantik yang sama persis" - datang terlambat ke pesta, tapi saya benar-benar tidak setuju dengan ini - seluruh titik penggunaan: sebelum dan: setelah ini adalah untuk dapat memasukkan gaya yang tidak mengganggu makna semantik Html.
Rupert
4

Ketika menulis ulang html diperbolehkan, Anda dapat membuat sarang <ul>di dalam <ul>dan membiarkan tampilan dalam <li>sebagai blok-inline. Ini juga semantik masuk akal IMHO, karena pengelompokan juga tercermin dalam html.


<ul>
    <li>
        <ul>
            <li>Item 1</li>
            <li>Item 2</li>
            <li>Item 3</li>
        </ul>
    </li>
    <li>
        <ul>
            <li>Item 4</li>
            <li>Item 5</li>
            <li>Item 6</li>
        </ul>
    </li>
</ul>

li li { display:inline-block; }

Demo

$(function() { $('img').attr('src', 'http://phrogz.net/tmp/alphaball.png'); });
h3 {
  border-bottom: 1px solid #ccc;
  font-family: sans-serif;
  font-weight: bold;
}
ul {
  margin: 0.5em auto;
  list-style-type: none;
}
li li {
  text-align: center;
  display: inline-block;
  padding: 0.1em 1em;
}
img {
  width: 64px;
  display: block;
  margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h3>Features</h3>
<ul>
  <li>
    <ul>
      <li><img />Smells Good</li>
      <li><img />Tastes Great</li>
      <li><img />Delicious</li>
    </ul>
  </li>
  <li>
    <ul>
      <li><img />Wholesome</li>
      <li><img />Eats Children</li>
      <li><img />Yo' Mama</li>
    </ul>
  </li>
</ul>

Fabb
sumber
3

Cara mudah untuk membagi daftar menjadi baris adalah dengan melayang item daftar individual dan kemudian item yang ingin Anda buka ke baris berikutnya Anda dapat menghapus float.

sebagai contoh

<li style="float: left; display: inline-block"></li>
<li style="float: left; display: inline-block"></li>
<li style="float: left; display: inline-block"></li>

<li style="float: left; display: inline-block; clear: both"></li> --- this will start on a new line
<li style="float: left; display: inline-block"></li>
<li style="float: left; display: inline-block"></li>
matt
sumber
17
Anda harus memperhatikan bahwa floatpengaturan menimpa inline-blockpengaturan. Mereka tidak benar-benar hidup berdampingan bersama
Itay
4
jika Anda menggunakan text-aling: center; itu tidak akan bekerja (istirahat mengambang itu)
Павел Иванов
3

Saya tahu Anda tidak ingin menggunakan pelampung dan pertanyaannya hanya teori tetapi jika ada yang menemukan ini berguna, inilah solusi menggunakan pelampung.

Tambahkan kelas kiri ke lielemen Anda yang ingin Anda apung:

<li class="left"><img src="http://phrogz.net/tmp/alphaball.png">Smells Good</li>

dan ubah CSS Anda sebagai berikut:

li { text-align:center; float: left; clear: left; padding:0.1em 1em }
.left {float: left; clear: none;}

http://jsfiddle.net/chut319/xJ3pe/

Anda tidak perlu menentukan lebar atau blok sebaris dan bekerja sejauh IE6.

chut319
sumber
1

Saya menyelesaikan ini dengan membuat pemilih :: before untuk elemen inline pertama di baris, dan membuat pemilih itu blok dengan margin atas atau bawah untuk memisahkan baris sedikit.

.1st_item::before
{
  content:"";
  display:block;
  margin-top: 5px;
}

.1st_item
{
  color:orange;
  font-weight: bold;
  margin-right: 1em;
}

.2nd_item
{
  color: blue;
}
Deji
sumber
-1

Perhatikan bahwa ini akan berhasil, tergantung bagaimana Anda merender halaman. Tetapi bagaimana kalau hanya memulai daftar unordered baru?

yaitu

<ul>
<li>
<li>
<li>
</ul>
<!-- start a new ul to line break it -->
<ul>

Phil LaNasa
sumber
-2

Solusi yang lebih baik adalah menggunakan -webkit-kolom: 2;

http://jsfiddle.net/YMN7U/889/

 ul { margin:0.5em auto;
-webkit-columns:2;
}
Vivekraj KR
sumber
Untuk beberapa kasus penggunaan, ini mungkin solusi yang masuk akal. Ini bukan solusi yang baik dalam hal ini, karena itu benar-benar memesan ulang konten untuk turun-lalu-menyeberang, bukan lintas-kemudian-turun.
Phrogz
5
Siapa yang ingin membuat aplikasi web yang hanya berfungsi di beberapa browser?
user2867288
-3

Mungkin itu sepenuhnya mungkin dengan hanya CSS tetapi saya lebih suka menghindari "melayang" sebanyak yang saya bisa karena itu mengganggu ketinggian orang tua itu.

Jika Anda menggunakan jQuery, Anda dapat membuat plugin `wrapN` sederhana yang mirip dengan` wrapAll` kecuali itu hanya membungkus elemen "N" dan kemudian memecah dan membungkus elemen "N" berikutnya menggunakan loop. Kemudian atur kelas pembungkus Anda ke `display: block;`.

(function ($) {
    $.fn.wrapN = function (wrapper, n, start) {
        if (wrapper === undefined || n === undefined) return false;
        if (start === undefined) start = 0;
        for (var i = start; i < $(this).size(); i += n)
           $(this).slice(i, i + n).wrapAll(wrapper);
        return this;
    };
}(jQuery));

$(document).ready(function () {
    $("li").wrapN("<span class='break' />", 3);
});

Berikut ini adalah JSFiddle dari produk jadi:

http://jsfiddle.net/dustinpoissant/L79ahLoz/

Dustin Poissant
sumber