Photowall with double sized highlight pictures - css

We are working on a picture gallery site and can't find a solution for following problem.
The picture wall contains several images. Some image (n Percent) should by highlighted and get displayed double sized on the wall.
The issue is, that I have no idea to fill the empty space left of the large picture, because its a new line.
Any ideas.
I created a fiddle for this sample here: Fiddle
<body>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size2">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
</body>
div {
background-color: #f00;
float: left;
}
.size1{
width: 100px;
height: 100px;
margin: 5px;
}
.size2{
width: 210px;
height: 210px;
margin: 5px;
}

Update:
The following browsers now natively support CSS Grid Layout.
Firefox v52
Chrome v57 for Linux, macOS, Windows, iOS, and Android
Safari v10.1
iOS Safari v10.3
Opera v44
This kind of layout requirement is what the CSS Grid Layout spec aims to address. The introduction to the spec reads:
Grid Layout is a new layout model for CSS that has powerful abilities to control the sizing and positioning of boxes and their contents. Unlike Flexible Box Layout, which is single-axis–oriented, Grid Layout is optimized for 2-dimensional layouts: those in which alignment of content is desired in both dimensions.
Native browser support for CSS Grid Layout is likely to start landing in major browsers soon (as shown here) and is currently featured behind a flag in some. For non-supporting browsers this JavaScript polyfill will be necessary.
As an example, CSS Grid Layout syntax is shown in the following CSS:
HTML
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box box--double">5</div>
<div class="box">7</div>
<div class="box">8</div>
...
</div>
</div>
CSS using the Grid layout model
.wrapper {
width: 600px;
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(7, 100px);
grid-template-rows: 100px 100px 100px;
grid-auto-flow: row;
}
.box {
background-color: #444;
color: #fff;
padding: 20px;
font-size: 150%;
margin: 5px;
}
.box--double {
background-color: red;
grid-column: 3 / span 2;
grid-row: 2 / span 2;
}
DEMO
Here is a fiddle which utilizes CSS Grid Layout syntax (inc. the polyfill) to provide a general gist.
Alternatively, Masonry may be able to achieve this, however long term this will always be dependent on JavaScript.
Responsive Web Design (RWD)
The CSS Grid Layout module includes several features to simplify the creation of responsive designs. Two pertinent features which address the issues raised in the comments are:
1 Flexible Lengths
The fr unit should be used instead of specifying the relative column width as a percentage. The main benefit of the fr unit is that it avoids having to manually recalculate the percentage when the number of columns change via a media query - (You simply change the value for the number of columns only):
/* Avoid using percentages like this */
.wrapper {
grid-template-columns: repeat(7, 14.286%);
...
}
/* Use the 'fr' unit instead */
.wrapper {
grid-template-columns: repeat(7, 1fr);
...
}
2 grid-auto-flow-dense
Three values that can be assigned to the grid-auto-flow property, namely row, column, and dense.
.wrapper {
grid-auto-flow: dense;
...
}
In some situations when row, or column values are used it can produce unwanted holes/gaps in the layout. When specifying dense an algorithm attempts to fill those holes/gaps in, however this can sometimes change the the order of the items. This feature is very similar to the way Masonry places items in a different position based on available vertical space.
DEMO FOR RWD
Here is a responsive fiddle that uses both the fr unit and the dense value to avoid any gaps/holes in the layout.
EDIT(5): Updated list of browsers supporting CSS Grid Layout.
EDIT(4): Added note regarding Chrome 57 implementing CSS Grid Layout spec.
EDIT(3): Added note regarding Firefox 52 implementing CSS Grid Layout spec.
EDIT(2): Add useful CSS Grid Layout features for achieving RWD
EDIT(1): Changed sample code to terse version and updated link to external fiddle

Here's a CSS only solution, fully responsive, based on CSS columns
.columns >div {
background-color: #f00;
float: left;
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
}
.size1{
width: 100px;
height: 100px;
margin: 5px;
}
.size2{
width: 210px;
height: 210px;
margin: 5px;
}
.columns {
width: 660px;
margin: 0 auto;
-webkit-columns: 200px 3;
-moz-columns: 200px 3;
columns: 200px 3;
-webkit-column-gap: 0;
-moz-column-gap: 0;
column-gap: 0;
}
#media (max-width: 689px) {
.columns {
width: 440px;
margin: 0 auto;
-webkit-columns: 200px 2;
-moz-columns: 200px 2;
columns: 200px 2;
}
}
#media (max-width: 459px) {
.columns {
display: flex;
flex-wrap: wrap;
max-width: 220px;
}
.columns div {
flex: 1 0 auto;
}
.columns .size1 {
flex-basis: calc(50% - 10px)
}
.columns .size2 {
flex-basis: calc(100% - 10px)
}
}
body {
padding: 0;
text-align: center;
}
#media (min-width: 920px) { /* 4 columns */
.columns {
width: 880px;
-webkit-columns: 200px 4;
-moz-columns: 200px 4;
columns: 200px 4;
}
}
#media (min-width: 1140px) { /* 5 columns */
.columns {
width: 1100px;
-webkit-columns: 200px 5;
-moz-columns: 200px 5;
columns: 200px 5;
}
}
#media (min-width: 1360px) { /* 6 columns */
.columns {
width: 1320px;
-webkit-columns: 200px 6;
-moz-columns: 200px 6;
columns: 200px 6;
}
}
#media (min-width: 1580px) {
/* respect the principle above to add as many columns as you like */
}
<div class="columns">
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
</div>
For mobiles media query interval, I used flexbox, but it's just to show it's possible. You really don't have to, you can stick to box-model.
Note: You can define further media intervals. The basic idea is to have a multiple of 220px and limit it to widths that have sufficient room for all columns.
Here's the fiddle (I added it as, for some reason, SO won't allow me to resize the snippet window under ~480px, while jsFiddle does.)
fiddle here
This solution assumes you will always pair 2 small items together (so they occupy 1 row). If you want a solution where this condition doesn't have to be met by whoever adds content, and automatically tries to pair small items when they are single, you need javascript.
Timeline solution (based on comments info)
I'm guessing this is what you need? (If you decide to change classnames, you'll need to adjust both js and CSS).
$('.timeline .size2').each(function(){
//moving required number of small'uns so they fill the column
var prevIndex = $(this).prevAll('.size2,.wrap').eq(0).index(),
diff = $(this).index() - (prevIndex + 1),
toMove = (3 - (diff % 3)) %3;
if (toMove) {
for (var i = 1; i < toMove + 1; i++) {
$(this).nextAll('.size1').eq(0).addClass('moved').insertBefore($(this))
}
}
var wrap = $('<div />', {
class:'wrap'
})
//wrap 2 small'uns to make a row under a big'un
for (var i = 0; i < 2; i++) {
wrap.append($(this).nextAll('.size1').eq(0));
}
wrap.insertAfter($(this));
})
.timeline [class^="size"] {
background-color: red;
}
.size1{
width: 100px;
height: 100px;
margin: 5px;
}
.size2{
width: 210px;
height: 210px;
margin: 5px;
}
.timeline {
display: flex;
flex-direction: column;
align-content: flex-start;
height: 330px;
flex-wrap: wrap;
}
.timeline .wrap {
display: inline-flex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="timeline">
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
</div>

I tried to shorten the fiddle from RobC and replaced the fixed width in pixels with relative width in percent. So it is a little more responsive. But still have some gaps which you may prevent with some rules, like "no 2 big boxes side by side" and so on.
The Html
<div class="wrapper">
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
</div>
The CSS
.wrapper {
width: 100%;
display: grid;
grid-template-columns: repeat(6, 16.666%);
grid-auto-flow: row;
}
#media screen and (max-width: 940px) {
.wrapper {
grid-template-columns: repeat(5, 20%);
}
}
#media screen and (max-width: 540px) {
.wrapper {
grid-template-columns: repeat(3, 33.333%);
}
}
.wrapper > img {
background-color: #444;
color: #fff;
border: solid 1px white;
}
.box::before {
content: ' ';
display: block;
padding-top: 100%;
}
.box--double {
background-color: red;
grid-column: auto / span 2;
grid-row: auto / span 2;
}
The fiddle

Related

pushing icons closer together in footer gone wrong?

im trying to create a footer with a few social media icons...however, the method i've tried has resulted in the following problem :
expectation:
reality:
as you can see i'm failing in bringing the social media icons closer together... i tried setting the columns flex % to - however that pulls everything closer together towards the left of the screen...
here is my .row and .column as well as the social media icons..
.row {
display: flex;
}
.column {
flex: 30%;
padding: 00px;
}
.marginauto1 {
margin: 30px auto 20px;
display: block;
horizontal-align; middle;
vertical-align: middle;
}
<footer class= "marginauto1">
<center><div class="row">
<div class="column">
<center><a class= "pointer" href="twitter_url">
first time taking a stab at this on my own and I'm just really stuck here.. any help or tips would be appreciated!
If you want to put all your icons together in the middle:
img{
height:50px;
}
div{
display:flex;
justify-content: center;
background-color:blue;
}
<footer>
<div>
<img src="data:image/png;base64,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">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRyFcxKQYRAhR9esHvHVZokZGCYFNC1_rMHhw&usqp=CAU">
</div>
</footer>
<center> tag will not applicable if you are using flexbox. Instead flex-box itself has some properties that you can make use of. In your use-case you can go with justify-content: center
.row{
display: flex;
justify-content: center;
}
.item{
color: red;
background: lightblue;
margin-left: 20px;
}
<footer class= "marginauto1">
<div class="row">
<div class="item 1">
<h1>Telegram</h1>
</div>
<div class="item 2">
<h1>Facebook</h1>
</div>
<div class="item 3">
<h1>Twitter</h1>
</div>
</div>
</footer>
If you don't want any space in between of 2 or more items you can remove the margin.
Its working as expected. You have defined .column with flex: 30%; which intrun will split into 3
flex-grow: 1;
flex-shrink: 1;
flex-basis: 30%;
So what have you done is allowing the element to grow till the available width with a minimum of 30% relative to the container. This is because the flex-basis is defined. This will be 33% each.
For your soution to work remove flex: 30%; from .column. This will take the width depending on the content.
If you want some gap between the element, try adding some margin or padding, I have used margin for that. Or you can set the width of column element.
Inorder to align the items center in horizontal axis, use justify-content: center; for the flex element.
Working Fiddle
.row {
display: flex;
justify-content: center;
}
.column {
padding: 0px;
margin-right: 20px;
}
.marginauto1 {
margin: 30px auto 20px;
display: block;
}
.pointer img {
width: 50px;
}
<footer class="marginauto1">
<div class="row">
<div class="column">
<a class="pointer" href="">
<img src="https://cdn1.iconfinder.com/data/icons/logotypes/32/twitter-512.png" alt="">
</a>
</div>
<div class="column">
<a class="pointer" href="">
<img src="https://cdn1.iconfinder.com/data/icons/logotypes/32/twitter-512.png" alt="">
</a>
</div>
<div class="column">
<a class="pointer" href="">
<img src="https://cdn1.iconfinder.com/data/icons/logotypes/32/twitter-512.png" alt="">
</a>
</div>
</div>
</footer>

Width of flex item is shrinking [duplicate]

This question already has an answer here:
flex items ignoring width
(1 answer)
Closed 1 year ago.
I have a DIV with "display: flex;" that contains 2 child DIVs next to each other. The first one is just a DIV that contains some ordered list items and the second DIV contains some images. The second DIV has display: flex and flex-wrap: wrap applied to it.
For some reason, when I give the first DIV a width of 200px, it's not working... it doesn't get a width of 200px. But if instead I give it a min-width of 200px, then it works and gets a width of 200px. I need to understand why does width not work while min-width works...
/* Parent container that contains 2 child DIVs */
.parent_flex_container {
display: flex;
}
/* First child DIV */
#desktop_sidemenu {
width: 200px;
}
/* Second child DIV */
.flex_container {
display: flex;
flex-wrap: wrap;
}
/* Images of the second child DIV */
.Cac {
max-width: 50%;
height: 50%;
margin-bottom: 20px;
padding: 0 5px;
}
<div class="parent_flex_container">
<div id="desktop_sidemenu">
<nav>
<ul>
<li>Arabic</li>
<li>Green tea</li>
</ul>
</nav>
</div>
<div>
<div id="Featured_grid">
<div class="grid_title_holder">
<h2>Featured</h2>
</div>
<div class="flex_container">
<div class="Cac">
<img src="images/cover1.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover2.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover1.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover2.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover1.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover2.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover1.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover2.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
</div>
</div>
</div>
</div>
So let's start with this when you using flexbox each child items will have 3 different elements which are:
flex-basis
flex-grow
flex-shrink
Where each of them has a different responsibility.
flex-basis
Flex-basis controls the default size of an element before it is manipulated by other Flexbox properties. It could be used as a width or height property. Let's see the below example:
.flexbox {
display: flex;
}
.red {
background: red;
flex-basis: 100px;
}
.green {
background: green;
flex-basis: 100px;
}
.blue {
background: blue;
flex-basis: 100px;
}
<div class="flexbox">
<div class="red">1</div>
<div class="green">2</div>
<div class="blue">3</div>
</div>
flex-grow
Now, when it comes to the property called flex-grow, the default is 0. That means the squares are not allowed to grow to take up space in the container. You can see the example below for more resolution:
.flexbox {
display: flex;
}
.red {
background: red;
flex-grow: 0;
}
.green {
background: green;
flex-grow: 0;
}
.blue {
background: blue;
flex-grow: 0;
}
<div class="flexbox">
<div class="red">1</div>
<div class="green">2</div>
<div class="blue">3</div>
</div>
So whats make a difference here, Well, let’s try incrementing flex-grow to 1 for every square:
.flexbox {
display: flex;
}
.red {
background: red;
flex-grow: 1;
}
.green {
background: green;
flex-grow: 1;
}
.blue {
background: blue;
flex-grow: 1;
}
<div class="flexbox">
<div class="red">1</div>
<div class="green">2</div>
<div class="blue">3</div>
</div>
flex-shrink
Flex-shrink is the opposite of flex-grow, determining how much a square is allowed to shrink. ts main use is to specify which items you want to shrink, and which items you don’t. By default, every square has a flex-shrink of 1. To see how shrink works see the below snippet:
.flexbox {
display: flex;
}
.red {
background: red;
flex-grow: 0;
flex-basis: 100px;
flex-shrink: 1;
}
.green {
background: green;
flex-grow: 0;
flex-basis: 100px;
flex-shrink: 0;
}
.blue {
background: blue;
}
<div class="flexbox">
<div class="red">1</div>
<div class="green">2</div>
<div class="blue">3</div>
</div>
NOTE: you have to resize the browser to see the difference in the above squares.
Actual answer
So your problem lies here in the flex-shrink property, hence default value of flex-shrink is 1 so it will look like this:
#desktop_sidemenu {
width: 200px;
flex-shrink: 1; /* default setting of browser */
}
So that is why the width property alone does not do the work for you which means your first div will be shrinked in order to prevent the boxes get out of order, then all you have to do to make it work is to give it a min-width: 200px or flex-shrink: 0.
NOTE: there is a shorthand for these three property called flex which you can give these three properties as one with the following order:
flex: 0 0 200px; /* flex-grow flex-shrink flex-basis */
For more information about these kinds of stuff, you can follow the MDN here.
I need to understand why does width not work while min-width works...
Because flex items are set, by default, to flex-shrink: 1, which means that they can shrink in order to minimize overflow of the container.
Your actual code (what the browser sees) is this:
#desktop_sidemenu {
width: 200px; /* author defined */
flex-shrink: 1; /* default setting */
}
You need to disable flex-shrink:
#desktop_sidemenu {
width: 200px;
flex-shrink: 0;
}
Now, because the item can't shrink below 200px, it's equivalent to min-width: 200px.
For more details, see "The flex-shrink factor" in my answer here:
What are the differences between flex-basis and width?

Is it possible to add spacing in an item without increasing its size?

I'm trying to add space between columns (which are inside a container with "display: flex;"), but for example let's say I have 2 columns columns with 50% width if I add margin to any of them. The only way I thought of "adding" some space between columns so they would not stick together is to create another container just to add margin,bg-color, padding etc.
Example of a grid based on 12 columns, where everything happens normally:
<!DOCTYPE html>
<html>
<head>
<style>
*,
*::after,
*::before {
margin: 0;
box-sizing: border-box;
}
.row {
display: flex;
flex-flow: row wrap;
}
/* based on 12 columns */
.col-hd-3 {
width: 25%;
}
</style>
</head>
<body>
<div class="row">
<div class="col-hd-3" style="background-color: red;">
test
</div>
<div class="col-hd-3" style="background-color: green;">
test
</div>
<div class="col-hd-3" style="background-color: yellow;">
test
</div>
<div class="col-hd-3" style="background-color: grey;">
test
</div>
</div>
</body>
</html>
Now, let's say I add margin to any column:
<! ---->
<div class = "row">
<div class = "col-hd-3" style = "background-color: red; margin: 12px;">
test
</ div>
<! ---->
the last column will go to the next line.
So the only thing that solves it is something like:
<!---->
<div class="row">
<div class="col-hd-3">
<div style="margin: 12px; padding: 5px; background-color: red;">
Test
</div>
</div>
<!---->
Am I sure about the solution, or is this something done wrong?
So as you are using display: flex you need to set flex-grow: 1; and flex-basis: 0; on your column or simply set flex: 1;.
Read: https://www.w3schools.com/cssref/css3_pr_flex.asp
The flex-grow defines the ability for a flex item to grow if necessary, and the flex-basis defines the default size of an element before the remaining space is distributed.
So:
.col-hd-3 {
max-width: 25%; /* COLUMN WILL NOT BE WIDER THAN 25% */
margin: 12px;
flex-basis: 0;
flex-grow: 1;
}
or you can use the flex shorthand:
.col-hd-3 {
max-width: 25%; /* COLUMN WILL NOT BE WIDER THAN 25% */
margin: 12px;
flex: 1;
}
*,
*::after,
*::before {
margin: 0;
box-sizing: border-box;
}
.row {
display: flex;
flex-flow: row wrap;
}
/* based on 12 columns */
.col-hd-3 {
width: 25%;
margin: 12px;
flex-basis: 0;
flex-grow: 1;
}
<div class="row">
<div class="col-hd-3" style="background-color: red;">
test
</div>
<div class="col-hd-3" style="background-color: green;">
test
</div>
<div class="col-hd-3" style="background-color: yellow;">
test
</div>
<div class="col-hd-3" style="background-color: grey;">
test
</div>
</div>

Change div order on foundation/bootstrap part of row

I have a design where I have 3 divs.
On desktop mode - 2 divs are in the same row, and on mobile mode each of them is a full row, but the order needs to change.
For example this is my HTML (using foundation CSS):
<div class="row">
<div class="mobile-first small-12 large-8 columns">FIRST</div>
<div class="mobile-last small-12 large-4 columns">LAST</div>
</div>
<div class="row">
<div class="mobile-middle large-12 small-12">MIDDLE</div>
</div>
What needs to happen when I am on mobile screen is that the "LAST" div will go last, even though it is part of the first row.
Is it possible without duplicating the HTML, using JS or using strange float that will act strange on some devices?
This is the fiddle I've made:
Fiddle
You can wrap mobile-first and mobile-middle divs into an additional column. Then apply negative margin-right to the mobile-middle div on the wide screen.
Please check the result:
1) Bootstrap
https://jsfiddle.net/glebkema/ss8zbf6z/
#import url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css');
.container {
margin: 0 auto;
max-width: 500px;
}
[class|="mobile"] {
height: 100px;
}
.mobile-first { background-color: blue; }
.mobile-last { background-color: red; }
.mobile-middle { background-color: green; }
#media (min-width: 992px) {
.mobile-middle {
margin-right: -33.33333333% !important;
width: 150% !important;
}
}
<div class="container">
<div class="row">
<div class="col-md-8">
<div class="row">
<div class="mobile-first col-xs-12">FIRST</div>
<div class="mobile-middle col-xs-12">MIDDLE</div>
</div>
</div>
<div class="mobile-last col-md-4">LAST</div>
</div>
</div>
2) Foundation
https://jsfiddle.net/glebkema/sbzgwf8t/
.container {
margin: 0 auto;
max-width: 500px;
}
[class|="mobile"] {
height: 100px;
}
.mobile-first { background-color: blue; }
.mobile-last { background-color: red; }
.mobile-middle { background-color: green; }
#media screen and (min-width: 64em) {
.mobile-middle {
margin-right: -33.33333% !important;
width: 150% !important;
}
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.2.3/foundation.css">
<div class="container">
<div class="row">
<div class="small-12 large-8 columns">
<div class="row">
<div class="mobile-first small-12 columns">FIRST</div>
</div>
<div class="row">
<div class="mobile-middle small-12 columns">MIDDLE</div>
</div>
</div>
<div class="mobile-last small-12 large-4 columns">LAST</div>
</div>
</div>
As per #moped suggest. I can use same row div for all the colums.
The solution is simple if they are all in the same div, I can use display: flex.
#media only screen and (max-width: 768px) {
.row {
display: flex;
flex-direction: column;
}
.mobile-first{
order: 1;
}
.mobile-last{
order: 3;
}
.mobile-middle{
order: 2;
}
updated fiddle

Overlapping elements within a square grid

I’ve to implement a layout based on a square grid. As shown on the following image, some elements have to overlap responsive within this grid. (The squares are offset on the x-axis and overlap by one grid cell on the y-axis.)
http://i.stack.imgur.com/9bZ5G.jpg
Does anybody know how to achieve this effect? I'm using the framework Foundation 6. I’d prefer a solution without JavaScript. I can’t use the Foundation .#-push-# and .#pull-# classes because they would shift the elements inwards and the two squares have to be in separate rows.
I’ve set up a JSFiddle containing the two squares.
.square {
background: #f00;
position: relative;
}
.square:after {
content: "";
display: block;
padding-bottom: 100%;
}
.content {
position: absolute;
width: 100%;
height: 100%;
}
.dark {
background: #cbcbcb;
}
.light {
background: #dedede;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.2.0/foundation.css" rel="stylesheet"/>
<div class="row">
<div class="small-12 columns">
<div class="row">
<div class="small-8 columns end">
<div class="square dark">
<div class="content">test</div>
</div>
</div>
</div>
<div class="row">
<div class="small-6 small-offset-6 columns end">
<div class="square light">
<div class="content">test</div>
</div>
</div>
</div>
</div>
</div>
Many thanks in advance for your help.
I know this question is a little bit old, but for the benefit of all this is now very easily and cleanly possible with CSS Grid. Taking the image posted in the original question we define a container and two squares:
<div class="container">
<div class="content square1">Square 1</div>
<div class="content square2">Square 2</div>
</div>
Then in the CSS define the container as a CSS Grid with 6 columns and 6 rows. In the example below I have used the repeat() CSS Method to have the browser create 6 of the same sized columns and rows.
.container {
display: grid;
grid-column-template: repeat(6, 1fr);
grid-row-template: repeat(6, 30px);
width: 100%;
height: 600px;
}
Then for each item you set where the upper left hand corner will be located on that grid. You can use the long handed properties of grid-column-start, grid-column-end, grid-row-start, and grid-row-end, but I find it's easier to use the short hand properties as shown below:
.square1 {
grid-column: 1 / 5;
grid-row: 1 / 5;
background: #cbcbcb;
}
.square2 {
grid-column: 4 / 7;
grid-row: 4 / 7;
background: #dedede;
}
As far as the placement goes, you specify it based on the grid lines you're invisibly drawing in the container. Position 1 / 1 in this case is the upper left-most corner (or where 0,0 would be if you're talking about coordinates). CSS Grid is now widely supported and I believe there are some JS libraries out there that do create fall backs for this if you don't want to hard code your own with feature queries.
Here's the full block of code with the SO Code Snippet runner:
.container {
display: grid;
grid-column-template: repeat(6, 1fr);
grid-row-template: repeat(6, 30px);
width: 100%;
height: 600px;
}
.square1 {
grid-column: 1 / 5;
grid-row: 1 / 5;
background: #cbcbcb;
}
.square2 {
grid-column: 4 / 7;
grid-row: 4 / 7;
background: #dedede;
}
<div class="container">
<div class="content square1">Square 1</div>
<div class="content square2">Square 2</div>
</div>
It seems to work if you calculate the offset with percent and also mind the column spacing. I therefore adjustet the snippet and added another square with 4 colums:
.square {
background: #f00;
position: relative;
}
.square:after {
content: "";
display: block;
padding-bottom: 100%;
}
.content {
position: absolute;
width: 100%;
height: 100%;
}
.dark {
background: #cbcbcb;
}
.light {
background: #dedede;
}
/* NEW */
.small-6.columns.overlap-top > .square {
margin-top: calc(-33.3% + 1.33*0.625rem); // one third is 33.3% minus 1.33 times col spacing
}
.small-4.columns.overlap-top > .square {
margin-top: calc(-50% + 1*0.625rem); // one half is 50% minus 1 times col spacing
}
#media screen and (min-width: 40em) {
.small-6.columns.overlap-top > .square {
margin-top: calc(-33.3% + 1.33*0.9375rem);
}
.small-4.columns.overlap-top > .square {
margin-top: calc(-50% + 1*0.9375rem);
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.2.0/foundation.css" rel="stylesheet"/>
<div class="row">
<div class="small-12 columns">
<div class="row">
<div class="small-8 columns end">
<div class="square dark">
<div class="content">Square 1</div>
</div>
</div>
</div>
<div class="row">
<!-- New class overlap-top -->
<div class="small-6 small-offset-6 columns overlap-top end">
<div class="square light">
<div class="content">Square 2</div>
</div>
</div>
</div>
<!-- New square -->
<div class="row">
<div class="small-4 small-offset-4 columns overlap-top end">
<div class="square dark">
<div class="content">Square 3</div>
</div>
</div>
</div>
</div>
</div>
JSFiddle: https://jsfiddle.net/jwt0k1pw/1/
Hope this helps!

Resources