Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

css

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.

like image 971
P-Gn Avatar asked Dec 15 '22 11:12

P-Gn


2 Answers

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>
like image 126
Type-Style Avatar answered May 28 '23 12:05

Type-Style


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>
like image 30
Aaron Avatar answered May 28 '23 11:05

Aaron