Flexbox container slightly taller than its contents - html

I have a flex container with 4 columns/flex items, each containing an image of the same size/proportions with the max-width set to 100%. Columns have an overflow property set to hidden since I want to scale images on hover but don't want them to expand outside their column's "boundaries". However, the container's height is 382px while the image height is 379.5px leaving a subtle gap of 2.5px on the bottom when hovering image. Please refer to the modified screenshot below (red line marks the bottom edge of the container, second/lighter image is in hover state) as well as the code.
I've tried setting the flex container's align-items property to center and I've tried removing whitespace in HTML, among other things, to no avail. I am trying to wrap my head around what might be causing this discrapency. From what I understand, the height of elements in CSS is determined by their children so I don't get why it's 382px in the first place if the height of each image is 379.5px.
Any help would be greatly apprecaited, thank you!
P.S. I'm using Eric Meyer's CSS reset.
<div class="flex">
<div class="flex-item">
<img src="./img/img01.jpg" alt="Image">
</div>
<div class="flex-item">
<img src="./img/img02.jpg" alt="Image">
</div>
<div class="flex-item">
<img src="./img/img03.jpg" alt="Image">
</div>
<div class="flex-item">
<img src="./img/img04.jpg" alt="Image">
</div>
</div>
.flex {
display: flex;
column-gap: 1em;
}
.flex-item {
flex: 1;
overflow: hidden;
}
.flex-item > img {
max-width: 100%;
transform: scale(1);
transition: all 0.2s ease-in-out;
}
.flex-item:hover > img {
transform: scale(1.125);
}

All what you need, just put to the .flex-item class display: flex.
.flex-item {
display: flex; /* new line */
flex: 1;
overflow: hidden;
}
*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.flex {
display: flex;
column-gap: 1em;
border: 1px solid red;
}
.flex-item {
display: flex; /* new line */
flex: 1;
overflow: hidden;
}
.flex-item > img {
max-width: 100%;
transform: scale(1);
transition: all 0.2s ease-in-out;
}
.flex-item:hover > img {
transform: scale(1.125);
}
<div class="flex">
<div class="flex-item">
<img src="https://plchldr.co/i/400x400?&bg=ece2d0&fc=000" />
</div>
<div class="flex-item">
<img src="https://plchldr.co/i/400x400?&bg=ece2d0&fc=000" />
</div>
<div class="flex-item">
<img src="https://plchldr.co/i/400x400?&bg=ece2d0&fc=000" />
</div>
<div class="flex-item">
<img src="https://plchldr.co/i/400x400?&bg=ece2d0&fc=000" />
</div>
</div>
Expample 2
.flex {
display: flex;
column-gap: 1em;
border: 1px solid red;
overflow: hidden;
}
img {
width: 100%;
height: 100px;
transition: all 0.2s ease-in-out;
}
.flex img:hover {
transform: scale(1.125);
}
<div class="flex">
<img src="https://plchldr.co/i/400x400?&bg=ece2d0&fc=000" />
<img src="https://plchldr.co/i/400x400?&bg=ece2d0&fc=000" />
<img src="https://plchldr.co/i/400x400?&bg=ece2d0&fc=000" />
<img src="https://plchldr.co/i/400x400?&bg=ece2d0&fc=000" />
</div>

Related

Fully responsiove images in 3 div's side by side

So I want these 3 div's to work side by side and the images to be responsive. when I try to set max-width or something it breaks up. Help me out on this one.
.fl {
display: flex;
flex-wrap: no-wrap;
height: 35%;
flex-direction: row;
}
.pic {
width: 34%;
}
.caro {
/* border: 2px solid black; */
height: 100%;
width: 100%;
display: block;
/* z-index: ; */
}
.caro img {
height: 100%;
width: 100%;
filter: brightness(0.5);
transition: all .3s;
}
.caro img:hover {
filter: brightness(1);
}
<div class="fl">
<div class="pic">
<img src="https://via.placeholder.com/1920x1080.jpg" alt="">
</div>
<div class="pic">
<img src="https://via.placeholder.com/1920x1080.jpg" alt="">
</div>
<div class="pic">
<img src="https://via.placeholder.com/1920x1080.jpg" alt="">
</div>
</div>
I would suggest two things:
Use calc to get a third with calc(100% / 3), instead of setting the width to a total of (3*34=) 102%.
Use object-fit: cover on the images to make them fit. I used different sizes on the images, so it's obvious that they are scaling.
Don't use all for transition, because that can cause janky animations due to the browser having to loop through all animatable properties. Always specify what you animate; it's easier to understand the code as well.
Using percentage for height doesn't automatically take the parent's height, so I had to improvise and use vh (viewport height).
body {
margin: 0px;
min-height: 100vh;
}
.fl {
display: flex;
flex-wrap: no-wrap;
height: 100vh;
max-height: 35vh;
}
.fl > .pic {
flex-basis: calc(100% / 3);
}
.caro img {
height: 100%;
width: 100%;
object-fit: cover;
filter: brightness(0.5);
transition: filter .3s;
}
.caro img:hover {
filter: brightness(1);
}
<div class="fl">
<div class="pic">
<img src="https://picsum.photos/100/300">
</div>
<div class="pic">
<img src="https://picsum.photos/50/80.jpg" alt="">
</div>
<div class="pic">
<img src="https://picsum.photos/100/100" alt="">
</div>
</div>

CSS Elements in columns are under the upper border while scale transforming

I have 4 columns of images using column-count and I want them to scale on mouse hover.
The first column works fine but the next three will be under the upper border while transforming.
I tried all kinds of margins and padding and I also tried z-index but it didn't work.
Here's live JSFiddle
Code:
.content{
margin-top: 20px;
background-color: black;
}
.photos img {
margin-bottom: 10px;
vertical-align: middle;
height: auto;
width: 100%;
}
.photos {
-webkit-column-count: 4;
-moz-column-count: 4;
column-count: 4;
-webkit-column-gap: 10px;
-moz-column-gap: 10px;
column-gap: 10px;
}
li img {
-webkit-transition: 0.2s;
}
li img:hover {
-webkit-transition: .5s;
transform: scale(1.3);
}
<div class="content">
<ul class="photos">
<li>
<img src="https://syndlab.com/files/view/5db9b150252346nbDR1gKP3OYNuwBhXsHJerdToc5I0SMLfk7qlv951730.jpeg">
</li>
<li>
<img src="https://lh3.googleusercontent.com/proxy/t2UjB23Xy8xLCPcwavD_5pqDWQH8wx1tOggm85KZq22oyODukZGZyMDIfGHwIKyZj1U4JeAzn3t5bkgPXcV8pJ60udJ1eQ">
</li>
<li>
<img src="https://images.all-free-download.com/images/graphicthumb/bavarian_landscape_515460.jpg">
</li>
<li>
<img src="https://cdn-ep19.pressidium.com/wp-content/uploads/2019/08/16-9-original-1.jpg">
</li>
</ul>
</div>
You can switch to flexbox and achieve the same behavior with no problem.
Just adjust you CSS like this:
.photos {
display: flex;
}
li {
width: 25%;
}
Here's a working live Codepen: https://codepen.io/alezuc/pen/jObWjLm
Update:
Ok so if you want to achieve what you post in the comment below I suggest you to move to a pure CSS Mansory approach. Here's the code:
Remove the column management and the list (ul/li) and use divs:
<div class="content">
<div class="item">
<img src="https://placehold.it/600x620.jpg">
</div>
<div class="item">
<img src="https://lh3.googleusercontent.com/proxy/t2UjB23Xy8xLCPcwavD_5pqDWQH8wx1tOggm85KZq22oyODukZGZyMDIfGHwIKyZj1U4JeAzn3t5bkgPXcV8pJ60udJ1eQ">
</div>
<div class="item">
<img src="https://images.all-free-download.com/images/graphicthumb/bavarian_landscape_515460.jpg">
</div>
<div class="item">
<img src="https://cdn-ep19.pressidium.com/wp-content/uploads/2019/08/16-9-original-1.jpg">
</div>
<div class="item">
<img src="https://cdn-ep19.pressidium.com/wp-content/uploads/2019/08/16-9-original-1.jpg">
</div>
<div class="item">
<img src="https://cdn-ep19.pressidium.com/wp-content/uploads/2019/08/16-9-original-1.jpg">
</div>
<div class="item">
<img src="https://images.all-free-download.com/images/graphicthumb/bavarian_landscape_515460.jpg">
</div>
<div class="item">
<img src="https://cdn-ep19.pressidium.com/wp-content/uploads/2019/08/16-9-original-1.jpg">
</div>
<span class="item break"></span>
<span class="item break"></span>
<span class="item break"></span>
</div>
Here's the CSS Code:
.content {
background-color: black;
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 */
padding: 0;
width: 100%;
margin: 40px auto;
counter-reset: items;
}
.item {
width: 24%;
/* Optional */
position: relative;
margin-bottom: 1%;
}
/* 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;
margin: 0;
content: "";
padding: 0;
}
img {
max-width: 100%;
height: auto;
transition: 0.2s;
}
img:hover {
transition: .5s;
transform: scale(1.12);
}
Here's the working live Codepen: https://codepen.io/alezuc/pen/MWayKaq
And here the reference where I get this kind of approach.
I think the problem with the columns is that the browser is "confused" and thinks the non-first images are more down below.
I found 2 possibilities to make this work, first my favorite: display: flex;
.content{
margin-top: 50px;
background-color: black;
}
.photos img {
margin-bottom: 10px;
vertical-align: middle;
height: auto;
width: 100%;
}
.photos {
padding: 0;
list-style: none;
display: flex;
}
.photos li{
flex-basis: 25%;
padding: 0 5px;
margin: 0;
}
li img {
-webkit-transition: 0.2s;
}
li img:hover {
-webkit-transition: .5s;
transform: scale(1.12);
}
<div class="content">
<ul class="photos">
<li>
<img src="https://syndlab.com/files/view/5db9b150252346nbDR1gKP3OYNuwBhXsHJerdToc5I0SMLfk7qlv951730.jpeg">
</li>
<li>
<img src="https://lh3.googleusercontent.com/proxy/t2UjB23Xy8xLCPcwavD_5pqDWQH8wx1tOggm85KZq22oyODukZGZyMDIfGHwIKyZj1U4JeAzn3t5bkgPXcV8pJ60udJ1eQ">
</li>
<li>
<img src="https://images.all-free-download.com/images/graphicthumb/bavarian_landscape_515460.jpg">
</li>
<li>
<img src="https://cdn-ep19.pressidium.com/wp-content/uploads/2019/08/16-9-original-1.jpg">
</li>
</ul>
</div>
the other possibilities using your column settings are dased around adding position: absolute to .photos img or float: left to .photos.
Edit: I see that Alessio created his answer while I was working on mine and he also uses float. Please accept his answer as the working one if you go with the float solution.

Centering flex children without extra space

MWE:
https://jsfiddle.net/zjgc9dfx/
Suppose I've got this layout:
<div class="slider">
<span>button here</span>
<div class="slide">
<img src="https://loremflickr.com/1000/1000" alt="Bacn">
</div>
<span>button here</span>
</div>
The slider is a flex container. The two buttons are inline-block, and I want the slide img to be limited to the viewport's height without extra space.
How can I achieve this?
* {
margin: 0;
padding: 0;
}
.slider {
display: flex;
justify-content: center;
align-items: center;
background-color: red;
}
.slider .slide img {
width: 100%;
max-height: 100%;
}
<div class="slider">
<span>asd</span>
<div class="slide">
<img src="https://loremflickr.com/1000/1000" alt="Bacn">
</div>
<span>asd</span>
</div>
Maybe something like this will work:
.slider {
display: flex;
align-items: center;
height: 100vh;
background-color: red;
}
.slider>span {
flex-shrink: 0; /* disables shrinking feature */
}
.slider>.slide {
flex: 1; /* consume all free space */
height: 100%;
}
.slider .slide img {
width: 100%;
max-height: 100%;
object-fit: cover;
vertical-align: bottom; /* https://stackoverflow.com/a/31445364/3597276 */
}
* {
margin: 0;
padding: 0;
}
<div class="slider">
<span>button here</span>
<div class="slide">
<img src="https://loremflickr.com/1000/1000" alt="Bacn">
</div>
<span>button here</span>
</div>
jsFiddle demo

Slightly rotating a div at the edge of the window without horizontal scrollbar appearing

At the top of a page, I created four boxes/tiles which slightly rotate on hover (5 degree rotation). The boxes are positioned and sized via flexbox to span the entire width of the window. When hovering over the rightmost box, its bottom right corner moves out of the window on the right, causing a horizontal scrollbar to appear.
I would like to avoid the scrollbar from appearing. I tried doing so by setting display: none for the <div> containing the boxes, but this interferes with showing the rotation of the boxes in general as it cuts them off at the div's border when they rotate. I would like to keep the effect of the boxes rotating fully visible and avoid the horizontal scrollbar at the same time.
Here's my html and css as well as a jsfiddle of the page (please note that the horizontal scrollbar does not always appear in the jsfiddle, depending on the size of the window in which the code is running):
.banner {
margin: 0px;
font-size: 10vw;
line-height: 1.2;
overflow-x: hidden;
}
.flex {
display: flex;
}
.row {
flex-direction: row;
justify-content: space-between;
}
.box {
flex: 1;
text-align: center;
border: 1px solid black;
background-color: white;
box-sizing: border-box;
cursor: default;
}
.rotate-right {
transition: all 400ms ease;
}
.rotate-left {
transition: all 400ms ease;
}
.rotate-right:hover {
transform: rotate(5deg);
}
.rotate-left:hover {
transform: rotate(-5deg);
}
<div class="top" id="top">
<div>
<div class="flex row banner">
<div class="box rotate-right">
<p>
1
</p>
</div>
<div class="box rotate-left">
<p>
2
</p>
</div>
<div class="box rotate-right">
<p>
3
</p>
</div>
<div class="box rotate-left">
<p>
4
</p>
</div>
</div>
</div>
</div>
Add overflow-x: hidden for your body. Demo:
body {
overflow-x: hidden;
}
* {
font-size: 6vw;
}
.flex {
display: flex;
}
.row {
flex-direction: row;
justify-content: space-between;
}
.box {
flex: 1;
text-align: center;
border: 1px solid black;
background-color: white;
box-sizing: border-box;
cursor: default;
}
.rotate-right {
transition: all 400ms ease;
}
.rotate-left {
transition: all 400ms ease;
}
.rotate-right:hover {
transform: rotate(5deg);
}
.rotate-left:hover {
transform: rotate(-5deg);
}
<div class="top" id="top">
<div>
<div class="flex row banner">
<div class="box rotate-right">
<p>
1
</p>
</div>
<div class="box rotate-left">
<p>
2
</p>
</div>
<div class="box rotate-right">
<p>
3
</p>
</div>
<div class="box rotate-left">
<p>
4
</p>
</div>
</div>
</div>
</div>
use this command inside your class name if it is span let say then use like this
//for chrome
.span {
&::-webkit-scrollbar{
display: none;
}
}
//for firefox
.span{
scrollbar-width: none;
}

How to put 2 rows of images inside a 'column' using flex boxes

I'm building a site using flex boxes. I have a div with 2 'columns' inside, and 2 'rows' inside of the second 'column' which I have to fill with two images each, the problem is the images doesn't fit into the 'rows' and exceeds its width.
I need my images stretch or shrink with the navigator size, so I can't use px for their size.
This is what I want:
And this is what I get:
Here is my code:
#offices {
background: peachpuff;
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.col {
background: yellow;
flex: 1;
}
.row {
background: red;
line-height: 0;
display: flex;
}
#officesImg img {
flex: 1;
width: 100%;
height: 100%;
}
<div id="offices">
<div class="col">
</div>
<div class="col" id="officesImg">
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
</div>
</div>
Here is a CODEPEN
PD: Please avoid float solutions.
You can set #officesImg to display:flex. And removed height:100% from the img that causes aspect ration issue on Firefox.
#offices {
background: peachpuff;
margin: 1em;
display: flex;
}
.col {
background: yellow;
margin: 1em;
flex: 1;
}
#officesImg {
line-height: 0;
display: flex;
}
#officesImg img {
width: 100%;
height: auto;
}
<div id="offices">
<div class="col">
</div>
<div class="col" id="officesImg">
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
</div>
</div>
Here is a slightly polished version that matches your wireframe.
#offices {
background: peachpuff;
margin: 1em;
display: flex;
}
.col {
background: yellow;
margin: 1em;
flex: 1;
}
#officesImg {
line-height: 0;
display: flex;
padding: .5em;
}
#officesImg img {
width: calc(100% - 1em);
height: auto;
margin: .5em;
}
<div id="offices">
<div class="col">
</div>
<div class="col" id="officesImg">
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
</div>
</div>
The quickest solution is to wrap each image element in a div.
In other words:
<div><img ... ></div>
Images remain responsive and aspect ratio is maintained.
Tested in Chrome, Firefox and IE11.
Revised Codepen