सीएसएस-केवल चिनाई लेआउट


134

मुझे एक काफी रन-ऑफ-द-मिल चिनाई लेआउट को लागू करने की आवश्यकता है। हालाँकि, कई कारणों से मैं इसे करने के लिए जावास्क्रिप्ट का उपयोग नहीं करना चाहता।

अलग-अलग ऊंचाई के आयतों के कई स्तंभों का एक ग्रिड।

पैरामीटर:

  • सभी तत्वों की चौड़ाई समान है
  • तत्वों की एक ऊंचाई है जो सर्वर साइड (एक छवि और पाठ की विभिन्न मात्रा) की गणना नहीं की जा सकती है
  • अगर मुझे करना है तो मैं निश्चित संख्या में कॉलम के साथ रह सकता हूं

वहाँ यह करने के लिए एक छोटी सी समाधान है कि आधुनिक ब्राउज़रों में काम करता है संपत्ति।column-count

उस समाधान के साथ समस्या यह है कि तत्वों को स्तंभों में क्रमबद्ध किया गया है:

शीर्ष बाएं बॉक्स से शुरू होकर, वे 4 सीधे नीचे से 1 नंबर पर हैं, अगले कॉलम में सबसे ऊपरी बॉक्स 5 है, और इसी तरह।

जबकि मुझे पंक्तियों में आदेश दिए जाने वाले तत्वों की आवश्यकता है, कम से कम लगभग:

सबसे ऊपरी बाएं बॉक्स से शुरू होकर, वे 6 सीधे 6 से होकर गुजरते हैं, लेकिन क्योंकि बॉक्स 5 सबसे छोटा बॉक्स है, यह 7 के नीचे है, क्योंकि इसमें बाईं ओर अगले बॉक्स की तुलना में एक पंक्ति में अधिक होने का आभास होता है।

मेरे द्वारा प्रयास किए गए दृष्टिकोण जो काम नहीं करते हैं:

अब मैं सर्वर साइड रेंडरिंग को बदल सकता था और स्तंभों की संख्या से आइटमों की संख्या को विभाजित करने वाली वस्तुओं को पुन: क्रमित कर सकता था , लेकिन यह जटिल है, त्रुटि-प्रवण (कैसे ब्राउज़र कॉलम में आइटम सूची को विभाजित करने का निर्णय लेते हैं) के आधार पर, इसलिए मैं चाहूंगा अगर संभव हो तो इससे बचें।

वहाँ कुछ newfangled flexbox जादू है कि यह संभव बनाता है?


7
ऐसा तरीका नहीं सोच सकते जो पूर्वनिर्धारित ऊंचाइयों पर निर्भर न हो। यदि आप JS पर पुनर्विचार करते हैं, तो stackoverflow.com/questions/13518653/… पर एक नज़र डालें जहाँ मैं ऐसे समाधान को लागू करता हूँ जो काफी सरल है।
गेब्रियल पेट्रीओली

1
@ Gaby आपके समाधान को अभी लागू कर रहा है, धन्यवाद!
पेका

4
मुझे एहसास है कि आपने सीएसएस-ओनली कहा था। मैं केवल यह उल्लेख करना चाहता हूं कि चिनाई को अब jQuery की आवश्यकता नहीं है - की गई लाइब्रेरी 8kb से कम है - और इसे अकेले HTML के साथ प्रारंभ किया जा सकता है। बस संदर्भ के लिए jsfiddle.net/wp7kuk1t
मैं

1
यदि आप लाइन-ऊँचाई, फ़ॉन्ट-आकार को जानकर समय से पहले तत्वों की ऊँचाई निर्धारित कर सकते हैं (आपको एक विशिष्ट फ़ॉन्ट परोसना होगा और कुछ चतुर गणनाएँ करनी होंगी), छवि की ऊँचाई, वर्टिकल मार्जिन और पैडिंग, आप कर सकते हैं यह करो। अन्यथा, आप केवल CSS का उपयोग करके ऐसा नहीं कर सकते। आप प्रत्येक तत्व को पूर्व-रेंडर करने और उस तत्व की ऊँचाई प्राप्त करने के लिए PhantomJS जैसी किसी चीज़ का उपयोग कर सकते हैं, लेकिन इसमें महत्वपूर्ण ओवरहेड / विलंबता जोड़ा जाएगा।
टिमोथी ज़ोर्न

जवाबों:


157

flexbox

एक गतिशील चिनाई लेआउट flexbox के साथ संभव नहीं है, कम से कम एक साफ और कुशल तरीके से नहीं।

फ्लेक्सबॉक्स एक आयामी लेआउट प्रणाली है। इसका मतलब यह है कि यह क्षैतिज या ऊर्ध्वाधर रेखाओं के साथ आइटम संरेखित कर सकता है। एक फ्लेक्स आइटम अपनी पंक्ति या स्तंभ तक ही सीमित है।

एक सच्ची ग्रिड प्रणाली द्वि-आयामी है, जिसका अर्थ है कि यह क्षैतिज और ऊर्ध्वाधर रेखाओं के साथ वस्तुओं को संरेखित कर सकती है। सामग्री आइटम पंक्तियों और स्तंभों पर एक साथ फैल सकते हैं, जो कि फ्लेक्स आइटम नहीं कर सकते हैं।

यही कारण है कि फ्लेक्सबॉक्स में ग्रिड के निर्माण की सीमित क्षमता होती है। यह भी एक कारण है कि W3C ने एक और CSS3 तकनीक, ग्रिड लेआउट विकसित किया है ।


row wrap

के साथ एक फ्लेक्स कंटेनर में flex-flow: row wrap, फ्लेक्स आइटम को नई पंक्तियों में लपेटना चाहिए ।

इसका मतलब यह है कि एक फ्लेक्स आइटम एक ही पंक्ति में किसी अन्य आइटम के नीचे लपेट नहीं सकता है

ऊपर दी गई सूचना कि कैसे # 3 div # 1 के नीचे लपेटता है , एक नई पंक्ति बनाता है। यह div # 2 के नीचे नहीं लपेट सकता ।

नतीजतन, जब आइटम पंक्ति में सबसे ऊंचे नहीं होते हैं, तो सफेद जगह बनी रहती है, जिससे भद्दे अंतराल बनते हैं।


column wrap

यदि आप स्विच करते हैं flex-flow: column wrap, तो ग्रिड जैसा लेआउट अधिक प्राप्य है। हालाँकि, एक स्तंभ-दिशा वाले कंटेनर में बल्ले से चार संभावित समस्याएं हैं:

  1. फ्लेक्स आइटम क्षैतिज रूप से बहते हैं, क्षैतिज रूप से नहीं (जैसे आपको इस मामले में ज़रूरत है)।
  2. कंटेनर क्षैतिज रूप से फैलता है, लंबवत नहीं (जैसे Pinterest लेआउट)।
  3. कंटेनर को एक निश्चित ऊंचाई की आवश्यकता होती है, इसलिए आइटम जानते हैं कि कहां लपेटना है।
  4. इस लेखन के रूप में, सभी प्रमुख ब्राउज़रों में इसकी कमी है जहां अतिरिक्त कॉलम को समायोजित करने के लिए कंटेनर का विस्तार नहीं होता है

नतीजतन, एक स्तंभ-दिशा कंटेनर इस मामले में, और कई अन्य मामलों में एक विकल्प नहीं है।


सीएसएस ग्रिड मद आयाम के साथ अपरिभाषित

ग्रिड लेआउट आपकी समस्या का एक सही समाधान होगा यदि सामग्री वस्तुओं की विभिन्न ऊंचाइयों को पूर्व-निर्धारित किया जा सकता है । ग्रिड की क्षमता के भीतर अन्य सभी आवश्यकताएं अच्छी तरह से हैं।

ग्रिड आइटम की चौड़ाई और ऊंचाई आसपास की वस्तुओं के साथ अंतराल को बंद करने के लिए जानी जानी चाहिए।

तो ग्रिड, जो कि सबसे अच्छी सीएसएस है, को क्षैतिज रूप से बहने वाली चिनाई लेआउट के निर्माण के लिए पेश करना पड़ता है, इस मामले में कम पड़ता है।

वास्तव में, जब तक सीएसएस तकनीक अंतराल को स्वचालित रूप से बंद करने की क्षमता के साथ आती है, तब तक सामान्य रूप से सीएसएस का कोई समाधान नहीं होता है। कुछ इस तरह से शायद दस्तावेज़ को फिर से भरने की आवश्यकता होगी, इसलिए मुझे यकीन नहीं है कि यह कितना उपयोगी या कुशल होगा।

आपको एक स्क्रिप्ट की आवश्यकता होगी।

जावास्क्रिप्ट समाधान निरपेक्ष स्थिति का उपयोग करते हैं, जो बिना किसी अंतराल के उन्हें फिर से व्यवस्थित करने के लिए दस्तावेज़ प्रवाह से सामग्री आइटम निकालता है। यहाँ दो उदाहरण हैं:


सीएसएस ग्रिड परिभाषित आइटम आयामों के साथ

लेआउट के लिए जहां सामग्री की चौड़ाई और ऊंचाई ज्ञात है, यहां शुद्ध सीएसएस में क्षैतिज रूप से बहने वाली चिनाई लेआउट है:

grid-container {
  display: grid;                                                /* 1 */
  grid-auto-rows: 50px;                                         /* 2 */
  grid-gap: 10px;                                               /* 3 */
  grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));   /* 4 */
}

[short] {
  grid-row: span 1;                                             /* 5 */
  background-color: green;
}

[tall] {
  grid-row: span 2;
  background-color: crimson;
}

[taller] {
  grid-row: span 3;
  background-color: blue;
}

[tallest] {
  grid-row: span 4;
  background-color: gray;
}

grid-item {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3em;
  font-weight: bold;
  color: white;
}
<grid-container>
  <grid-item short>01</grid-item>
  <grid-item short>02</grid-item>
  <grid-item tall>03</grid-item>
  <grid-item tall>04</grid-item>
  <grid-item short>05</grid-item>
  <grid-item taller>06</grid-item>
  <grid-item short>07</grid-item>
  <grid-item tallest>08</grid-item>
  <grid-item tall>09</grid-item>
  <grid-item short>10</grid-item>
  <grid-item tallest>etc.</grid-item>
  <grid-item tall></grid-item>
  <grid-item taller></grid-item>
  <grid-item short></grid-item>
  <grid-item short></grid-item>
  <grid-item short></grid-item>
  <grid-item short></grid-item>
  <grid-item tall></grid-item>
  <grid-item short></grid-item>
  <grid-item taller></grid-item>
  <grid-item short></grid-item>
  <grid-item tall></grid-item>
  <grid-item short></grid-item>
  <grid-item tall></grid-item>
  <grid-item short></grid-item>
  <grid-item short></grid-item>
  <grid-item tallest></grid-item>
  <grid-item taller></grid-item>
  <grid-item short></grid-item>
  <grid-item tallest></grid-item>
  <grid-item tall></grid-item>
  <grid-item short></grid-item>
</grid-container>

jsFiddle डेमो


यह काम किस प्रकार करता है

  1. एक ब्लॉक-स्तरीय ग्रिड कंटेनर स्थापित करें। ( inline-gridअन्य विकल्प होगा)
  2. grid-auto-rowsसंपत्ति स्वतः उत्पन्न पंक्तियों की ऊंचाई निर्धारित करता है। इस ग्रिड में प्रत्येक पंक्ति 50px लंबी है।
  3. grid-gapसंपत्ति के लिए एक आशुलिपि है grid-column-gapऔर grid-row-gap। यह नियम ग्रिड आइटम के बीच 10px का अंतर निर्धारित करता है । (यह आइटम और कंटेनर के बीच के क्षेत्र पर लागू नहीं होता है।)
  4. grid-template-columnsसंपत्ति स्पष्ट रूप से परिभाषित स्तंभों की चौड़ाई निर्धारित करता है।

    repeatअंकन दोहरा कॉलम (या पंक्तियाँ) के एक पैटर्न को परिभाषित करता है।

    auto-fillसमारोह ग्रिड बताता कंटेनर बह निकला बिना के रूप में कई कॉलम (या पंक्तियाँ) संभव के रूप में पंक्तिबद्ध करने के लिए। (यह फ्लेक्स लेआउट के समान व्यवहार बना सकता है flex-wrap: wrap।)

    minmax()समारोह प्रत्येक स्तंभ (या पंक्ति) के लिए एक न्यूनतम और अधिकतम आकार सीमा निर्धारित करता है। ऊपर दिए गए कोड में, प्रत्येक कॉलम की चौड़ाई कंटेनर का न्यूनतम 30% होगी और जो भी खाली स्थान उपलब्ध है, उसमें से अधिकतम।

    frइकाई ग्रिड कंटेनर में मुक्त अंतरिक्ष के एक अंश का प्रतिनिधित्व करता है। यह Flexbox की flex-growसंपत्ति के बराबर है ।

  5. के साथ grid-rowऔर spanहम ग्रिड आइटम को बता रहे हैं कि उन्हें कितनी पंक्तियों में भर जाना चाहिए।


सीएसएस ग्रिड के लिए ब्राउज़र समर्थन

  • Chrome - 8 मार्च, 2017 तक पूर्ण समर्थन (संस्करण 57)
  • फ़ायरफ़ॉक्स - 6 मार्च 2017 तक पूर्ण समर्थन (संस्करण 52)
  • सफारी - 26 मार्च 2017 तक पूर्ण समर्थन (संस्करण 10.1)
  • एज - 16 अक्टूबर 2017 तक पूर्ण समर्थन (संस्करण 16)
  • IE11 - वर्तमान कल्पना के लिए कोई समर्थन नहीं; अप्रचलित संस्करण का समर्थन करता है

यहां देखें पूरी तस्वीर: http://caniuse.com/#search=grid


फ़ायरफ़ॉक्स में कूल ग्रिड ओवरले सुविधा

फ़ायरफ़ॉक्स डेव टूल्स में, जब आप ग्रिड कंटेनर का निरीक्षण करते हैं, तो सीएसएस घोषणा में एक छोटा ग्रिड आइकन होता है। क्लिक करने पर यह पृष्ठ पर आपके ग्रिड की रूपरेखा प्रदर्शित करता है।

अधिक विवरण यहां: https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts


5
शानदार जवाब! "सीएसएस ग्रिड के साथ आइटम आयामों के साथ परिभाषित" समाधान, क्या सेल चौड़ाई के प्रतिशत के रूप में सेल की ऊंचाई को व्यक्त करना संभव है? यह छवियों को प्रदर्शित करने के लिए उपयोगी होगा, जहां पहलू अनुपात ज्ञात है। हम हर समय पहलू अनुपात बनाए रखना चाहते हैं।
ओलिवर जोसेफ ऐश

धन्यवाद। छवियों के लिए पहलू अनुपात मुद्दे के संबंध में, "सेल चौड़ाई का प्रतिशत" विधि (प्रतिशत पैडिंग ट्रिक?), यह उस मामले के लिए ग्रिड या फ्लेक्सबॉक्स में विश्वसनीय नहीं है। यहाँ और यहाँ देखें । @ ऑलिवरजॉस्फ एश
माइकल बेंजामिन

हां, मैं प्रतिशत पैडिंग ट्रिक की बात कर रहा हूं। क्या आपके चिनाई लेआउट समाधान के संयोजन में किसी भी प्रकार के वर्कअराउंड का उपयोग करना संभव है? संदर्भ के लिए, हम unsplash.com पर छवियों के लिए एक सीएसएस केवल चिनाई लेआउट को लागू करने के लिए देख रहे हैं ।
ओलिवर जोसेफ ऐश

1
दुर्भाग्य से इसके लिए जेएस का उपयोग करना एक विकल्प नहीं है। हम प्रदर्शन और एसईओ कारणों के लिए सर्वर साइड रेंडरिंग को सक्षम करना चाहते हैं। इसका मतलब है कि क्लाइंट-साइड जावास्क्रिप्ट को डाउनलोड करने, पार्स करने और निष्पादित करने से पहले लेआउट को प्रदान किया जाना चाहिए। यह असंभव प्रतीत होता है, मुझे लगता है कि हमें लाइन से कहीं दूर व्यापार करना होगा! आपकी मदद के लिए धन्यवाद :-)
ओलिवर जोसेफ ऐश

1
विशेष अद्यतन: फ्लेक्सबॉक्स में, प्रतिशत मार्जिन और पेडिंग अब कंटेनर के इनलाइन आकार को फिर से हल करने के लिए सेट किए गए हैं। draft.csswg.org/css-flexbox/#item-margins @OliverJosephAsh
माइकल बेंजामिन

13

यह हाल ही में खोजी गई तकनीक है जिसमें flexbox शामिल है: https://tobiasahlin.com/blog/masonry-with-css/

लेख मेरे लिए समझ में आता है, लेकिन मैंने इसका उपयोग करने की कोशिश नहीं की है, इसलिए मुझे नहीं पता कि माइकल के जवाब में उल्लेख किए जाने के अलावा कोई अन्य विवरण हैं या नहीं।

यहाँ लेख का एक नमूना है, orderसंपत्ति का उपयोग , के साथ संयुक्त :nth-child

ढेर स्निपेट

.container {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  /* Your container needs a fixed height, and it 
   * needs to be taller than your tallest column. */
  height: 960px;
  
  /* Optional */
  background-color: #f7f7f7;
  border-radius: 3px;
  padding: 20px;
  width: 60%;
  margin: 40px auto;
  counter-reset: items;
}

.item {
  width: 24%;
  /* Optional */
  position: relative;
  margin-bottom: 2%;
  border-radius: 3px;
  background-color: #a1cbfa;
  border: 1px solid #4290e2;
  box-shadow: 0 2px 2px rgba(0,90,250,0.05),
    0 4px 4px rgba(0,90,250,0.05),
    0 8px 8px rgba(0,90,250,0.05),
    0 16px 16px rgba(0,90,250,0.05);
  color: #fff;
  padding: 15px;
  box-sizing: border-box;
}

 /* Just to print out numbers */
div.item::before {
  counter-increment: items;
  content: counter(items);
}

/* Re-order items into 3 rows */
.item:nth-of-type(4n+1) { order: 1; }
.item:nth-of-type(4n+2) { order: 2; }
.item:nth-of-type(4n+3) { order: 3; }
.item:nth-of-type(4n)   { order: 4; }

/* Force new columns */
.break {
  flex-basis: 100%;
  width: 0;
  border: 1px solid #ddd;
  margin: 0;
  content: "";
  padding: 0;
}

body { font-family: sans-serif; }
h3 { text-align: center; }
<div class="container">
  <div class="item" style="height: 140px"></div>
  <div class="item" style="height: 190px"></div>
  <div class="item" style="height: 170px"></div>
  <div class="item" style="height: 120px"></div>
  <div class="item" style="height: 160px"></div>
  <div class="item" style="height: 180px"></div>
  <div class="item" style="height: 140px"></div>
  <div class="item" style="height: 150px"></div>
  <div class="item" style="height: 170px"></div>
  <div class="item" style="height: 170px"></div>
  <div class="item" style="height: 140px"></div>
  <div class="item" style="height: 190px"></div>
  <div class="item" style="height: 170px"></div>
  <div class="item" style="height: 120px"></div>
  <div class="item" style="height: 160px"></div>
  <div class="item" style="height: 180px"></div>
  <div class="item" style="height: 140px"></div>
  <div class="item" style="height: 150px"></div>
  <div class="item" style="height: 170px"></div>
  <div class="item" style="height: 170px"></div>
  
  <span class="item break"></span>
  <span class="item break"></span>
  <span class="item break"></span>
</div>


सबसे पहले, लिंक केवल उत्तर खराब है, जैसे कि जब लिंक की मृत्यु हो जाती है, तो उत्तर क्या होता है। दूसरा, यदि आप दिए गए उत्तर को अधिक ध्यान से पढ़ते हैं, तो आप पाएंगे कि आपके लिंक में जो उल्लेख किया गया है वह कवर किया गया है। सीधे शब्दों में कहें, अकेले फ्लेक्सबॉक्स का उपयोग करते हुए बहुत सी सीमाएँ हैं, जब तक कि ऊपर उल्लिखित एक मुद्दा नहीं है।
आसन

3
मैंने स्वीकार किए गए उत्तर को बहुत अच्छी तरह से पढ़ा है - आप कुछ टिप्पणियाँ भी देखेंगे जिन्हें मैंने इसके नीचे जोड़ा था। मेरे द्वारा जुड़ा फ्लेक्सबॉक्स दृष्टिकोण अद्वितीय है और उस उत्तर द्वारा कवर नहीं किया गया है। मैं लेख को दोहराना नहीं चाहता, क्योंकि यह बहुत जटिल है, और यह लेख उस कवर करने का एक बड़ा काम करता है।
ओलिवर जोसेफ ऐश

केवल एक चीज जो अलग-अलग करती है वह orderसंपत्ति का उपयोग कर रही है, जिससे यह दिखता है कि आइटम बाएं से दाएं बहते हैं। फिर भी, इसकी मुख्य चाल है flex-flow: column wrap, जिसका उल्लेख उपरोक्त उत्तर में है। इसके अलावा, यह वस्तुओं को उस तरह से प्रवाहित नहीं कर सकता है जिस तरह से एक वास्तविक चिनाई करता है, उदाहरण के लिए यदि 3rd और 4th आइटम 3rd कॉलम में फिट होंगे, तो वे लिंक नहीं करेंगे। लेकिन फिर से जैसा कि मैंने कहा, यह सब इस बात पर निर्भर करता है कि आवश्यकताएं क्या हैं, और इस मामले में (यह सवाल), यह उस तरह से काम नहीं करेगा जैसा कि उसने पूछा था।
असोन

इसके अलावा, यह "आप लेख को दोहराना नहीं चाहते हैं" के बारे में नहीं है , एक उत्तर में कोड का आवश्यक हिस्सा होना चाहिए, इसलिए यह तब भी मान्य होगा जब जुड़ा हुआ संसाधन मर जाता है।
असोन

3
मैंने इसे अपडेट किया, लेख + एक अपवोट से एक नमूना जोड़ा।
असोन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.