Vertical alignment of blocks with different heights in CSS [duplicate] - css

This question already has answers here:
How to Create Grid/Tile View? [duplicate]
(8 answers)
Closed 7 years ago.
I am trying to achieve an effect similar to this. That is, I have some blocks (here, articles) that have the same width but can have different heights, and I want them to be next to their upper neighbors. When displaying the article inline and using a top vertical alignment, the articles still stay on their lines as expected:
<html>
<head>
<style>
article { display: inline-block; vertical-align: top; width:200px; margin:5px; background-color:#D0D0D0; }
</style>
</head>
<body>
<div style="width:630px; background-color:#F0F0F0">
<article style="height:100px;"></article><article style="height:200px;"></article><article style="height:300px;"></article><article style="height:200px;"></article><article style="height:200px;"></article><article style="height:100px;"></article>
</div>
</body>
</html>
I guess this would be easier if I would set the articles into predefined columns then align vertically within this columns, but AFAICT this is not the case in the example given above (with possibly the advantage of being able to dynamically change the number of columns).
Is this even possible to do this in CSS? Or are they using some complicated JavaScript to achieve this?
(Also as a side note, I need to have articles next to each other without line breaks to prevent spurious white spaces to appear in between, but this doesn't seem to be a problem in the page above).
EDIT
An important behavior of the page I linked that I failed to mention is that the articles are displayed more or less in the same order than they are listed, so that chronological order is preserved for example.

There are a couple option here, it all depends on the order you want the blocks to be in and the space between the elements.
You can see all the techniques in action in the script below.
In short. CSS might not be enough here.
First lets look at all the CSS-techniques that might be helpful here.
Display: inline-block;
Display: table;
Floats
columns
flexbox
display: inline-block lets you control the vertical-alignment.
And you the order is left to right.
But the space is not used properly.
display: table behaves about the same as inline-block; (Depends on the settings) But it wont help here much.
floats: uses the space better.
But it behaves kinda strange. (Try to switch the elements in the DOM here.)
colums: Uses the space very well.
But the order is based on columns, and not the text-direction.
And you might run in couple of webkit specific bugs here.
flexbox: Can do very much for you.
Controlling the order here is tricky. Since the wrap is based on columns.
Otherwise it would behave similar to inline-block;
JS too the rescue.
I hate to admit it but javascript might be the right choice here.
There is something called isotope or masonry that you could use.
This way the order is based on text-direction and the space is used properly.
...
There are other CSS Techniques you could use and maybe get a better result.
But those have limited browser support by now:
CSS Regions
CSS Grid Layout
$(function(){
$('.masonry').masonry({
// options
itemSelector : '.masonry article'});
});
hr {
clear: left;
}
article {
width: 32%;
margin-top: 15px;
color: #fff;
font-size: 20px;
}
.inline-block article {
display: inline-block;
vertical-align: top;
}
.float article {
float: left;
width: 32%;
margin-left: 3px;
}
.columns {
-webkit-column-count: 3;
-moz-column-count: 3;
column-count: 3;
-webkit-column-gap: 0;
-moz-column-gap: 0;
column-gap: 0;
}
.columns article{
width: 100%;
}
.flexbox {
display: flex;
flex-direction: column;
flex-wrap: wrap;
max-height: 500px;
}
.flexbox article {
margin-left: 3px;
}
.masonry article {
margin-left: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://desandro.github.io/masonry/jquery.masonry.min.js"></script>
Inline-block:
<div class="inline-block">
<article style="height:300px;background:red">1</article>
<article style="height:100px; background:blue">2</article>
<article style="height:200px;background:green">3</article>
<article style="height:100px;background:orange">4</article>
<article style="height:200px;background:purple">5</article>
<article style="height:200px;background:black">6</article>
</div>
<hr />
Floats:
<div class="float">
<article style="height:300px;background:red">1</article>
<article style="height:100px; background:blue">2</article>
<article style="height:200px;background:green">3</article>
<article style="height:100px;background:orange">4</article>
<article style="height:200px;background:purple">5</article>
<article style="height:200px;background:black">6</article>
</div>
<hr />
Columns:
<div class="columns">
<article style="height:300px;background:red">1</article>
<article style="height:100px; background:blue">2</article>
<article style="height:200px;background:green">3</article>
<article style="height:100px;background:orange">4</article>
<article style="height:200px;background:purple">5</article>
<article style="height:200px;background:black">6</article>
</div>
<hr />
Flexbox:
<div class="flexbox">
<article style="height:300px;background:red">1</article>
<article style="height:100px; background:blue">2</article>
<article style="height:200px;background:green">3</article>
<article style="height:100px;background:orange">4</article>
<article style="height:200px;background:purple">5</article>
<article style="height:200px;background:black">6</article>
</div>
<hr />
Masonry (JS):
<div class="masonry">
<article style="height:300px;background:red">1</article>
<article style="height:100px; background:blue">2</article>
<article style="height:200px;background:green">3</article>
<article style="height:100px;background:orange">4</article>
<article style="height:200px;background:purple">5</article>
<article style="height:200px;background:black">6</article>
</div>

You could use CSS columns.
div {
width: 630px;
background-color: #F0F0F0
}
div {
-webkit-column-count: 3;
-moz-column-count: 3;
column-count: 3;
-webkit-column-gap: 0;
-moz-column-gap: 0;
column-gap: 0;
}
<div>
<article style="height:100px; background:blue"></article>
<article style="height:200px;background:green"></article>
<article style="height:300px;background:red"></article>
<article style="height:200px;background:purple"></article>
<article style="height:200px;background:black"></article>
<article style="height:100px;background:orange"></article>
</div>

I have tried many different ways of accomplishing this with CSS and in my humble opinion (and I hate to say it) this is impossible with CSS alone.
Flexbox, Grids, Columns, Table-Layouts, floats... none of the techniques I tried was able to handle this specific layout problem.
What was the closest I could get is with either flexbox or float combined with clearfixes. Yet, you will run in a lot of layout issues when your website is responsive.
The underlying issue is that you don't know the height of your containers beforehand. You would have to calculate the height and rearrange all other containers according to it (and you would have to do this for every container created in the future/past).
So, you could try with CSS and you might get close (counting boxes by the way is possible with CSS when ignoring old browsers – nth-child selectors will do that for you) but you will not come to the point where your layout is as flexible as within that demo (blaskdemo) you provided – unfortunately that is.

Related

How to create a clean four-column, left-aligned, layout using justify-content: space-between

I am trying to create a display blog post component with Flexbox that primarily uses justify-content: space-between. In a 4-column layout, it looks great when there are 4 posts to fill the row. The issue is when there are not 4 posts, but 2 or 3. At this point, the posts get spread out and it just looks sloppy. I want to use flexbox without any JavaScript, and I want to be able to have the layout be fully responsive. So at other breakpoints the column layout will drop to 3, 2, or even 1.
One of the things that I found that works great is adding an :after pseudo element to the wrapper with a set width that will fill in the empty space. The problem with that is it is not dynamic enough and will not work properly if I have a different number of post then the one I planned for.
For example: If I have 2 posts, each at 25% width, and then a pseudo element at 50% width, everything looks great. Once I have 3 posts it is not so great because the 50% pseudo element now needs to be 25%. Finally, if there is 4 I wouldn't need a pseudo element at all.
I am trying to work with using some of the SASS selectors, but for some reason when I try to target the parent with my :after element, it targets something else way up the DOM tree.
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.entry:nth-child( 2 ):last-of-type {
:after & {
content: "";
flex-grow: 0;
width: 50%;
}
}
.entry:nth-child( 3 ):last-of-type {
:after & {
content: "";
flex-grow: 0;
width: 50%;
}
}
}
At this point I expected the :after element to target the parent class "content" but it doesn't. I also didn't think about how I would adjust it to be more dynamic and be able to handle multiple rows. I guess I could just do the math and make it something like .entry:nth-child( 3n+4 ):last-of-type {}, but I haven't even gotten there yet.
CSS-Grid would seem to be a better fit than flexbox here.
.content {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 1em;
margin-bottom: 1em;
}
.red .entry {
background: red;
}
.blue .entry {
background: blue;
}
.green .entry {
background: green;
}
.entry {
height: 50px;
}
<div class="content red">
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
</div>
<div class="content blue">
<div class="entry"></div>
<div class="entry"></div>
<div class="entry"></div>
</div>
<div class="content green">
<div class="entry"></div>
<div class="entry"></div>
</div>
Here is a grid solution in Code Pen
For this to work in your query template it would look like this:
<div class="post-grid>
//while loop here
<div class="each-post">
<img src="<?php get_the_post_thumbnail() ?>">
<h2><?php get_the_title() ?></h2>
<p><?php get_the_excerpt() ?></p>
</div>
// end loop here
</div>

How to use two-column layout with reveal.js?

I use reveal.js and write my slides in Markdown code. Now I want to display my content (text, unordered list of bullet points or even an image) in a classical two-column text layout. I would prefer a solution which may be more complex in initial configuration as long as the actual writing of content in Markdown remains easy.
Since I prefer not to run a local server, I write my markdown within the main HTML file.
Update: As the first answer indicates this should be achieved with CSS. (I updated my question accordingly.) Still, I couldn't find any description how to do it with CSS.
I am using CSS flex, it is working fine.
<style>
.container{
display: flex;
}
.col{
flex: 1;
}
</style>
<div class="container">
<div class="col">
Column 1 Content
</div>
<div class="col">
Column 2 Content
</div>
</div>
UPDATE:
Since pandoc supports fenced div,
::: {.container}
:::: {.col}
Column 1 Content
::::
:::: {.col}
Column 2 Content
::::
:::
For the style, we can either use flex or grid, both work fine.
Using flex
<style>
.container{
display: flex;
}
.col {
flex: 1;
}
</style>
Using grid
<style>
.container{
display: grid;
grid-auto-flow: column;
}
</style>
I created two ID's in an external css file, custom.css, which I attached to my reveal.js file with the field css: custom.css in the YAML header.
#left {
left:-8.33%;
text-align: left;
float: left;
width:50%;
z-index:-10;
}
#right {
left:31.25%;
top: 75px;
float: right;
text-align: right;
z-index:-10;
width:50%;
}
I placed div elements with the right and left ID's in my markdown document to produce a two column layout.
<div id="right">
- You can place two graphs on a slide
- Or two columns of text
- These are all created with div elements
</div>
.multiCol {
display: table;
table-layout: fixed; // don't fudge depending on content
width: 100%;
text-align: left; // matter of taste, makes imho sense
.col {
display: table-cell;
vertical-align: top;
width: 50%;
padding: 2% 0 2% 3%; // some vertical, and between columns
&:first-of-type { padding-left: 0; } // there's nothing before col1
}
}
Put this into your custom theme, i.e. right before
// Theme template ------------------------------
#import "../template/theme";
// ---------------------------------------------
How to use? – easy! And not limited to 2 columns:
<section>
<h3>Doing two-column (this headline still full-width)</h3>
<div class='multiCol'>
<div class='col'>
Gallia est omnis divisa in partes tres, quarum unam incolunt Belgae, aliam Aquitani, tertiam qui ipsorum lingua Celtae, nostra Galli appellantur.
</div>
<div class='col'>
Qua de causa Helvetii quoque reliquos Gallos virtute praecedunt, quod fere cotidianis proeliis cum Germanis contendunt, cum aut suis finibus eos prohibent aut ipsi in eorum finibus bellum gerunt.
</div>
</div>
And simply more regular full-width text in the following. But hey, there is also:
<div class='multiCol'>
<div class='col'>Also works for 3 columns...</div>
<div class='col'>...as we can show in...</div>
<div class='col'>...this example here.</div>
</div>
</section>
No float needed
no clearfix needed
size independent (→ only percentages used)
2 columns, 3 columns, 4 columns ...
<table> ist often considered “outdated” (since it got so badly abused for layout purposes in early html days, and still today for html in emails...) but to the contrary at least as a property layout:table it has many legit uses, is often the most simple solution and widely compatible.
The CSS Grid Layout allows very flexible layouts, two-column formats and more complex layouts.
For two columns, the following CSS snippet may be used. It defines two column templates with equal size, each 1 fraction (1fr) of the available width, and a gutter space of 10px between the columns.
.twocolumn {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 10px;
text-align: left;
}
It can be used as follows
<section>
<h2>Slide Title</h2>
<div class="twocolumn">
<div>
Column One
</div>
<div>
Column Two
</div>
</div>
</section>
I solved the problem with two floating <div>-Elements:
<section>
<div style="text-align: left; float: left;">
<p data-markdown>- This is my first left element</p>
<p data-markdown>- This is my second left element</p>
<!-- more Elements -->
</div>
<div style="text-align: right; float: right;">
<p data-markdown>- This is my first right element</p>
<p data-markdown>- This is my second rightelement</p>
<!-- more Elements -->
</div>
</section>
I found out, if you want to use markdowns inside the div-container, you have to wrap the elements in p-tags. If you write data-markdown into the parent section-Tag, it will be ignored inside the div
I hope I could help!
I have found the following way to show one element in such a way it seems to be in a column layout
Text going to the right <!-- .element: style="float: right; width: 40%" -->
Text going on the left column <!-- .element: style="width: 40%" -->
But actually it doesn't work with more than one element on the right
I could not understand you completely but I guess you may found the answer in ramnathv post.
---
layout: slide
---
{{{ content }}}
<div class='left' style='float:left;width:{{left.width}}'>
{{{ left.html }}}
</div>
<div class='right' style='float:right;width:{{right.width}}'>
{{{ right.html }}}
</div>
it worked for me

how to use css to display multiple posts in inline-block like google+

I'm fetching a several post from my database I will like the post to displaY inline-block. Well it display but is not perfect. I want it to display. Like google+ posts. The problem I detect is when the comment in the post in the left not equal to the one in the right that's y it not position well. I av use several display method and its not working.
<style type="text/css">
/* this is the holder of the posts */
#container{
width: 900px;
overflow: auto;
}
.posts{
width: 400px;
padding: 20px;
display: inline-block;
margin: 2px 2px;
}
</style>
I want it to display like google+ posts which display inline even if the posts is longer than other. Any suggestion will b appreciate
Google+ separates its content into 3 columns. Nothing is set to display inline. To replicate this your markup would look something like this:
<div id="container">
<section>
<article class="posts">Post 1</article>
<article class="posts">Post 4</article>
</section>
<section>
<article class="posts">Post 2</article>
<article class="posts">Post 5</article>
</section>
<section>
<article class="posts">Post 3</article>
<article class="posts">Post 6</article>
</section>
</div>
#container {
display: block;
}
#container section {
float: left;
width: 33.33%;
}
#container section .posts {
display: block;
}
If you do want to do this in an inline fashion (similar to how Pinterest does it), you'll need to use JavaScript (or server-side code) to calculate the heights and widths of each .posts element and offset the element surrounding it appropriately (similar to this jQuery plugin I made last month).

How do I line up 3 divs on the same row?

Can someone please help me with this problem as i have been dealing with it for a long time now....
I am trying to get 3 divs on the same line next to each other one of the divs looks like this:
<div>
<h2 align="center">San Andreas: Multiplayer</h2>
<div align="center">
<font size="+1">
<em class="heading_description">15 pence per slot</em>
</font>
<img src="http://fhers.com/images/game_servers/sa-mp.jpg" class="alignleft noTopMargin" style="width: 188px; ">
<a href="gfh" class="order-small">
<span>order</span></a>
</div>
and the other two are the same divs please help me get all three divs on the same line one on the right one on the mid and one on the left
I'm surprised that nobody gave CSS table layout as a solution:
.Row {
display: table;
width: 100%; /*Optional*/
table-layout: fixed; /*Optional*/
border-spacing: 10px; /*Optional*/
}
.Column {
display: table-cell;
background-color: red; /*Optional*/
}
<div class="Row">
<div class="Column">C1</div>
<div class="Column">C2</div>
<div class="Column">C3</div>
</div>
Works in IE8+
Check out a JSFiddle Demo
See my code
.float-left {
float:left;
width:300px; // or 33% for equal width independent of parent width
}
<div>
<h2 align="center">San Andreas: Multiplayer</h2>
<div align="center" class="float-left">CONTENT OF COLUMN ONE GOES HERE</div>
<div align="center" class="float-left">CONTENT OF COLUMN TWO GOES HERE</div>
<div align="center" class="float-left">CONTENT OF COLUMN THREE GOES HERE</div>
</div>
I'm not sure how I ended up on this post but since most of the answers are using floats, absolute positioning, and other options which aren't optimal now a days, I figured I'd give a new answer that's more up to date on it's standards (float isn't really kosher anymore).
.parent {
display: flex;
flex-direction:row;
}
.column {
flex: 1 1 0px;
border: 1px solid black;
}
<div class="parent">
<div class="column">Column 1</div>
<div class="column">Column 2<br>Column 2<br>Column 2<br>Column 2<br></div>
<div class="column">Column 3</div>
</div>
here are two samples: http://jsfiddle.net/H5q5h/1/
one uses float:left and a wrapper with overflow:hidden. the wrapper ensures the sibling of the wrapper starts below the wrapper.
the 2nd one uses the more recent display:inline-block and wrapper can be disregarded. but this is not generally supported by older browsers so tread lightly on this one. also, any white space between the items will cause an unnecessary "margin-like" white space on the left and right of the item divs.
Old topic but maybe someone will like it.
fiddle link http://jsfiddle.net/74ShU/
<div class="mainDIV">
<div class="leftDIV"></div>
<div class="middleDIV"></div>
<div class="rightDIV"></div>
</div>
and css
.mainDIV{
position:relative;
background:yellow;
width:100%;
min-width:315px;
}
.leftDIV{
position:absolute;
top:0px;
left:0px;
height:50px;
width:100px;
background:red;
}
.middleDIV{
height:50px;
width:100px;
background:blue;
margin:0px auto;
}
.rightDIV{
position:absolute;
top:0px;
right:0px;
height:50px;
width:100px;
background:green;
}
2019 answer:
Using CSS grid:
.parent {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr;
}
Just add float left property on all the divs you want to make appear in a row other than last one. here is example
<div>
<div style="float: left;">A</div>
<div style="float: left;">B</div>
<div>C</div>
</div>
This is easier and gives purpose to the never used unordered/ordered list tags.
In your CSS add:
li{float: left;} //Sets float left property globally for all li tags.
Then add in your HTML:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
Now watch it all line up perfectly! No more arguing over tables vs divs!
Check out the foundation rapid prototyping framework they handled this quite nicely, basically they allow you to use HTML like this:
<div class="row">
<div class="four columns">
</div>
<div class="four columns">
</div>
<div class="four columns">
</div>
</div>
This is the simplest HTML/CSS grid system that I've come across, it's based on 12 column grid.
Basically the columns are given a % width and left margin relative to the parent row. They columns have float set to left, position set to relative, and display set to block.
The row has several properties set on it that care core of an issue that normally causes the containing div to collapse to height of 0 preventing the following divs from getting 'pushed' down as they should.
You can find examples of using the foundation grid system here: http://foundation.zurb.com/docs/grid.php
If you don't want to use the entire framework the following CSS should do the trick with the example code I provided:
.row:after {
content: "";
clear: both;
display: table;
}
.four.column {
float: left;
width: 33%;
}
If you really specifically want a left center and right columns then use code like this:
CSS:
.row:after {
content: "";
clear: both;
display: table;
}
.left {
float: left;
width: 100px;
}
.center {
margin: 0 auto;
width: 100px;
}
.right {
float: right;
width: 100px;
}
HTML:
<div class="row">
<div class="left">left</div>
<div class="right">right</div>
<div class="center">center</div>
</div>
Put the divisions in 'td' tag. That's it done.
Another possible solution:
<div>
<h2 align="center">
San Andreas: Multiplayer
</h2>
<div align="center">
<font size="+1"><em class="heading_description">15 pence per
slot</em></font> <img src=
"http://fhers.com/images/game_servers/sa-mp.jpg" class=
"alignleft noTopMargin" style="width: 188px;" /> <a href="gfh"
class="order-small"><span>order</span></a>
</div>
</div>
Also helpful as well.
Why don't try to use bootstrap's solutions. They are perfect if you don't want to meddle with tables and floats.
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/> <!--- This line is just linking the bootstrap thingie in the file. The real thing starts below -->
<div class="container">
<div class="row">
<div class="col-sm-4">
One of three columns
</div>
<div class="col-sm-4">
One of three columns
</div>
<div class="col-sm-4">
One of three columns
</div>
</div>
</div>
No meddling with complex CSS, and the best thing is that you can edit the width of the columns by changing the number. You can find more examples at https://getbootstrap.com/docs/4.0/layout/grid/

CSS: DIV containing no height on float set

Given the following code:
<div id='upperDiv' style='min-height:200px'>
<div id='rightDiv' style='float:right; width:75%'>
content1
</div>
<div id='leftDiv' style='float:left; width:25%'>
content2
</div>
</div>
<div id='lowerDiv' style='height:50px; margin-top:5px'>
content3
</div>
When content of rightDiv and leftDiv passes the 200px height (the value of min-height), upperDiv does not grow, so its content overlaps the lower div.
If the float attribute is removed from the large content, it grows and causes problems.
I do not know which of rightDiv or leftDiv exceeds 200px inheight.
How can this be fixed?
Set #upperDiv any of the following:
overflow: hidden;
width: 100%;
or
float: left;
width: 100%;
or create a rule using CSS pseudo-elements (IE8+ compatible) like this
#upperDiv:after {
content: "";
display: table;
clear: both;
}
Best solution
Creating a reusable class rule like the following.
.group:after {
content: "";
display: table;
clear: both;
}
Now you can apply it to anything that needs this same functionality. For example...
<div id='upperDiv' class="group" ... >
P.S. If you require IE 6/7 compatibility, checkout this post.
This is intentional as floats are designed for things like images in paragraphs (where multiple paragraphs can wrap around the image).
Complex Spiral has a fuller explanation as to why and Ed Elliot describes a number of approaches to making containers expand around floats. I find the overflow: hidden approach works best in most situations.
After
<div id='leftDiv' style='float:left;width:25%;'>
content2
</div>
add
<div style="clear:both"></div>
It will solve your problem.
There is a new property introduced recently display: flow-root; Which will fix this issue without any hacks and have almost all major support
<div id='upperDiv' style='border: 1px solid #000000; display: flow-root;'>
<div id='rightDiv' style='float:right;width:75%;'>
content1
</div>
<div id='leftDiv' style='float:left;width:25%;'>
content2
</div>
</div>
<div id='lowerDiv' style='height:50px;border: 1px solid #000000;margin-top:5px;'>
content3
</div>

Resources