This question already has answers here:
CSS-only masonry layout
(4 answers)
How to wrap flexbox over multiple rows and columns?
(3 answers)
Closed 4 years ago.
Question:
Is there any way to make layout like left to right masonry without JS?
! Please note I do not need exactly masonry, it works a bit different way !
Required:
Left to right order;
Each item goes to next column (items in masonry can pick columns out of order if available space on higher position);
Height is not fixed;
I can't change original order (1,2,3... but not 1,4,7...).
Example:
This one solution is almost what I looking for, but order is broken - example
HTML:
<div class="masonry">
<div class="item">1. (should be #1) ...</div>
<div class="item">2. (should be #4) ...</div>
<div class="item">3. (should be #7) Lorem ipsum dolor sit amet, consectetur adipisicing elit. Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div class="item">4. (should be #2) Lorem ipsum dolor sit amet, consectetur adipisicing. elit</div>
<div class="item">5. (should be #5) Lorem ipsum dolor sit asonsfd foindfosindf met, consectetur adipisicing elit.</div>
<div class="item">6. (should be #8) Lorem ipsum dolor sit amet, consectetur adipisicing. elit</div>
<div class="item">7. (should be #3) Lorem ipsum dolor sit amet, consectetur adipisicing elit.</div>
<div class="item">8. (should be #6) Lorem ipsum adipisicing elit. Lorem ipsum dolor sit elit</div>
<div class="item">9. (should be #9) Lorem ipsum dolor sit amet, consectetur adipisicing. elit</div>
</div>
CSS:
body {
font: 1em/1.67 'Open Sans', Arial, Sans-serif;
margin: 0;
background: #e9e9e9;
}
.wrapper {
width: 95%;
margin: 3em auto;
}
.masonry {
margin: 1.5em 0;
padding: 0;
-moz-column-gap: 1.5em;
-webkit-column-gap: 1.5em;
column-gap: 1.5em;
text-align:left;
font-size: .85em;
-moz-column-count: 3;
-webkit-column-count: 3;
column-count: 3;
}
.item {
display: inline-block;
background: #fff;
padding: 1em;
margin: 0 0 1.5em;
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-shadow: 2px 2px 4px 0 #ccc;
}
When ordering your html divs, you have to think differently.
If you draw your grid on a piece of paper, you can then draw rings around the columns and you get:
You want this:
1, 2, 3
4, 5, 6
7, 8, 9
You have to order like this:
1, 4, 7
2, 5, 8
3, 6, 9
Just re-order your html lines from columns to rows, like so:
<div class="masonry">
<div class="item">1. (should be #1) ...</div>
<div class="item">4. (should be #2) Lorem ipsum dolor sit amet, consectetur adipisicing. elit</div>
<div class="item">7. (should be #3) Lorem ipsum dolor sit amet, consectetur adipisicing elit.</div>
<div class="item">2. (should be #4) ...</div>
<div class="item">5. (should be #5) Lorem ipsum dolor sit asonsfd foindfosindf met, consectetur adipisicing elit.</div>
<div class="item">8. (should be #6) Lorem ipsum adipisicing elit. Lorem ipsum dolor sit elit</div>
<div class="item">3. (should be #7) Lorem ipsum dolor sit amet, consectetur adipisicing elit. Lorem ipsum dolor sit amet, consectetur adipisicing elit</div>
<div class="item">6. (should be #8) Lorem ipsum dolor sit amet, consectetur adipisicing. elit</div>
<div class="item">9. (should be #9) Lorem ipsum dolor sit amet, consectetur adipisicing. elit</div>
</div>
Related
I am trying to indent elements based on the heading tag they are under. I am doing this currently by using the sibling selector:
p{
padding-left: 0;
}
h1 + p, h1 + ul{
padding-left: 1em;
}
h2 + p{
padding-left: 2em;
}
However if have two or more paragraphs under a heading then the padding defaults back to zero.
Is there a way to set padding of all elements under h1 tag to the same value and all elements under the h1 tag to a different value (only using CSS)?
Thanks for the help!
You could do something like this:
h1+div {
padding-left: 1rem;
}
h2+div {
padding-left: 2rem;
}
<h1>My Title</h1>
<div>
<p>Lorem Ipsum Dolor sit amet</p>
<p>Lorem Ipsum Dolor sit amet</p>
<p>Lorem Ipsum Dolor sit amet</p>
<p>Lorem Ipsum Dolor sit amet</p>
<p>Lorem Ipsum Dolor sit amet</p>
</div>
<h2>My Title</h2>
<div>
<p>Lorem Ipsum Dolor sit amet</p>
<p>Lorem Ipsum Dolor sit amet</p>
<p>Lorem Ipsum Dolor sit amet</p>
<p>Lorem Ipsum Dolor sit amet</p>
<p>Lorem Ipsum Dolor sit amet</p>
</div>
There is also a way to achieve the same effect using only CSS, but I wont especially reccommend it:
h1 ~ p, h1 ~ ul {
padding-left: 1rem;
}
h2 ~ p, h2 ~ ul {
padding-left: 2rem;
}
<h1>My title</h1>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<h2>My title</h2>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
I made a working example what I want to achieve: Tabs fill up the given space evenly, if the text is too long, it is truncated with ellipsis.
The problem starts, if I wrap it into flex div. (It is a legacy code and part of complex template, and I want ot make as little change as possible)
.box {
border: 2px dotted rgb(96, 139, 168);
}
.box div {
min-width: 0px;
display: flex;
align-items: center;
border: 2px solid rgb(96, 139, 168);
border-radius: 5px;
background-color: rgba(96, 139, 168, .2);
}
<script src="https://cdn.tailwindcss.com"></script>
<b>Expected</b>
<div class="box h-16 flex items-stretch">
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
</div>
<b>Wrong</b>
<div id="wrapper" class="w-full mb-8 flex items-stretch">
<div class='mr-2 flex items-center'>
<a class="truncate">Link 1</a>
<a class="truncate">Link 2</a>
</div>
<div class="box h-16 flex items-stretch">
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
</div>
</div>
The problem, that in the second example the tabs do not shrink, they expand the viewport with a scrollbar.
Here is the jsbin
You just need to add width and overflow properties to the ".box" div. working example below.
.box {
border: 2px dotted rgb(96, 139, 168);
/* ADD THESE PROPERTIES */
width: 100%;
overflow: hidden;
}
.box div {
min-width: 0px;
display: flex;
align-items: center;
border: 2px solid rgb(96, 139, 168);
border-radius: 5px;
background-color: rgba(96, 139, 168, .2);
}
<script src="https://cdn.tailwindcss.com"></script>
<b>Expected</b>
<div class="box h-16 flex items-stretch">
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
</div>
<b>Wrong</b>
<div id="wrapper" class="w-full mb-8 flex items-stretch">
<div class='mr-2 flex items-center'>
<a class="truncate">Link 1</a>
<a class="truncate">Link 2</a>
</div>
<div class="box h-16 flex items-stretch">
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
<div><span class="truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span></div>
</div>
</div>
I'm try to have 100vh viewport with multiple responsive overlay on top of that
Here is the code, I can make header element get fixed on the viewport with position sticky but for the rest that doesn't work
Also, I'm trying to use CSS Grid for this
Here is the code
body {
display: grid;
grid-template-columns: 1fr minmax(20em, 30vw);
grid-template-rows: clamp(3em, 10vh, 5em) 1fr clamp(7em, 20vh, 9em);
}
header {
background-color: #eee;
grid-column: 1 / end;
grid-row: 1 / 2;
}
main {
height: 100vh;
grid-column: 1 / end;
grid-row: 1 / end;
}
aside {
background-color: #ccc;
grid-column: 2 / end;
grid-row: 2 / end;
}
footer {
background-color: #444;
grid-row: 3 / end;
grid-column: 1 / end;
}
<body>
<header></header>
<main>
<section class="questions" id="objectives">
<h2>Objectives</h2>
<div class="question">
<h3>1. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>2. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>3. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>4. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>5. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>6. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>7. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>8. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>9. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
</section>
</main>
<aside></aside>
<footer></footer>
</body>
Codepen https://codepen.io/ikamy/pen/rNYwOwM
Please vertically minimize and then scroll
I'm trying to fix footer and aside without using position fixed or absolute
While the body is display Grid I'm trying to use with: 100vh on the body and make the other Grid elements sticks , and I only scroll on the main element
You need to use min-height:100vh instead of height:100vh
And then use position:sticky on element you want to be sticky with top or bottom.
body {
display: grid;
grid-template-columns: 1fr minmax(20em, 30vw);
grid-template-rows: clamp(3em, 10vh, 5em) 1fr clamp(7em, 20vh, 9em);
}
header {
background-color: #eee;
grid-column: 1 / end;
grid-row: 1 / 2;
}
main {
min-height:100vh;
grid-column: 1 / end;
grid-row: 1 / end;
}
aside {
background-color: #ccc;
grid-column: 2 / end;
grid-row: 2 / end;
position: sticky;
top: 0;
z-index:99999;
}
footer {
background-color: #444;
grid-row: 3 / end;
grid-column: 1 / end;
position: sticky;
bottom: 0
;
}
<body>
<header></header>
<main>
<section class="questions" id="objectives">
<h2>Objectives</h2>
<div class="question">
<h3>1. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>2. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>3. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>4. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>5. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>6. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>7. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>8. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
<div class="question">
<h3>9. Lorem ipsum dolor sit amet, consectetur adipisicing.</h3>
<button>Yes</button><button>No</button>
</div>
</section>
</main>
<aside></aside>
<footer></footer>
</body>
For reference you may look at this question: 'position: sticky' not working when 'height' is defined
so i kinda new on web development scene and there is something i want to know how to make, here is the list that i want to make
https://i.imgur.com/PAQaJde.png
what is that bar thing called? and how to make it stay on top when i scrolled
https://i.imgur.com/ai0Vf2g.png
is this card or simple col that get styled using css?
sorry for the dumb question guys, i really kinda lost since i dont know how those thing called
1) Its called a navigation, or a navBar, and you position it absolute at 0,0 for it to stay up the top:
2) not sure what you are asking for your second question but to get it in that style. you can use CSS Grid, or FlexBox which are both native browser functionality.
Im happy to answer any further questions :)
welcome to the community
The first one is a navbar or navigation bar. You can make it stick to the top by setting position: fixed; top: 0; left:0; z-index:99;
nav {
position: fixed;
display: block;
top: 0;
left: 0;
height: 50px;
width: 100%;
padding: 10px;
background-color: #ccc;
}
.block {
display: block;
height: 1000px;
}
<nav>
Navbar
</nav>
<div class='block'>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
</div>
The second one you can achieve by nesting an element inst=ide another, applying a margin to the parent and border-radius to the child. It works with any layout style.
div{
border: solid 1px #ccc;
border-radius: 5px;
}
.container {
padding: 20px;
}
.card {
display: inline-block;
width: 100px;
height: 100px;
margin-right: 20px;
}
.card-wide {
display: inline-block;
width: 150px;
height: 50px;
margin-top: 30px;
margin-right: 30px;
}
<div class='container'>
<h1>Content</h1>
<div class='card'></div>
<div class='card'></div>
<div class='card'></div>
<br />
<div class='card-wide'></div>
<div class='card-wide'></div>
<div class='card-wide'></div>
<div class='card-wide'></div>
</div>
Is there a more elegant way of achieving this via CSS? The idea is to shape text like an Arc.
Thanks!
#p1 {
text-indent: 0;
}
#p2 {
text-indent: 10px;
}
#p3 {
text-indent: 20px;
}
#p4 {
text-indent: 30px;
}
#p5 {
text-indent: 40px;
}
#p6 {
text-indent: 30px;
}
#p7 {
text-indent: 20px;
}
#p8 {
text-indent: 10px;
}
#p9 {
text-indent: 0px;
}
<p id="p1">Lorem ipsum dolor sit amet</p>
<p id="p2">Lorem ipsum dolor sit amet</p>
<p id="p3">Lorem ipsum dolor sit amet</p>
<p id="p4">Lorem ipsum dolor sit amet</p>
<p id="p5">Lorem ipsum dolor sit amet</p>
<p id="p6">Lorem ipsum dolor sit amet</p>
<p id="p7">Lorem ipsum dolor sit amet</p>
<p id="p8">Lorem ipsum dolor sit amet</p>
<p id="p9">Lorem ipsum dolor sit amet</p>
If you want a perfect arc you can use shape-outside to create a circle or ellipse that the text will follow.
You can see how this works
However support is spotty to say the least.
div{
shape-outside: circle(50%);
width: 140px;
height: 140px;
float: left;
}
<div></div>
<span>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</span>
You can achieve the same result with one class and one rule on that class. The trick is to repeat the elements inside each other:
.blubb {
margin: 5px 0 5px 10px;
}
<div class="blubb">
Lorem ipsum dolor sit amet
<div class="blubb">
Lorem ipsum dolor sit amet
<div class="blubb">
Lorem ipsum dolor sit amet
<div class="blubb">
Lorem ipsum dolor sit amet
<div class="blubb">Lorem ipsum dolor sit amet</div>
</div>
<div class="blubb">Lorem ipsum dolor sit amet</div>
</div>
<div class="blubb">Lorem ipsum dolor sit amet</div>
</div>
<div class="blubb">Lorem ipsum dolor sit amet</div>
</div>
<div class="blubb">Lorem ipsum dolor sit amet</div>
As Dale said, use shape-outside for a pure css solution. However due to browser support we have to find a lower-level solution.
Contains comments for non-jQuery solution, code contains jQuery.
var ps = 9;//paragraphs
var i = 1;//start id
var x = 0;//left position
var amount = 50;
for(i=1;i<ps;i++){
//calculate left position in arc
//(i/ps) gets value between 0 and 1, Math.PI is to make it radians for sine, *amount is max indent
//bearing in mind this bit can be changed to give more desired effect.
x = Math.sin(((i-1)/(ps-1))*Math.PI)*amount;
//get element using jquery and set its text-indent to x
//otherwise you could use document.getElementById('p'+i); and textIndent JS property if you dont want jQuery.
$('#p'+i).css('text-indent', x+'px');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="p1">Lorem ipsum dolor sit amet</p>
<p id="p2">Lorem ipsum dolor sit amet</p>
<p id="p3">Lorem ipsum dolor sit amet</p>
<p id="p4">Lorem ipsum dolor sit amet</p>
<p id="p5">Lorem ipsum dolor sit amet</p>
<p id="p6">Lorem ipsum dolor sit amet</p>
<p id="p7">Lorem ipsum dolor sit amet</p>
<p id="p8">Lorem ipsum dolor sit amet</p>
<p id="p9">Lorem ipsum dolor sit amet</p>