Keep row height on animated flex boxes - css

I'm using flex to display as set of divs and animating the images by setting their width to 95% on hover. This is my CSS:
.container {
display: flex;
flex-wrap: wrap;
align-content: center;
}
.box {
display: flex;
flex-direction: column;
justify-content: center;
margin-top: 1.5%;
align-items: center;
flex: 0 1 48%;
}
.img-container img {
width: 100%;
transition: width ease-in 0.15s;
}
.img-container:hover img {
width: 95%;
transition: width ease-in 0.15s;
}
My problem is that, because of the animation duration, if I hover on images from the top row, for a brief moment both animations are active, forcing the row's height to decrease, which makes the elements beneath it bounce up and down.
Is there a way to force the row to keep its height constant during these animations?
.container {
display: flex;
flex-wrap: wrap;
align-content: center;
}
.box {
display: flex;
flex-direction: column;
justify-content: center;
margin-top: 1.5%;
align-items: center;
margin-right: 2%;
flex: 0 1 48%;
}
.box:nth-of-type(2n) {
margin-right: 0;
}
.img-container {
text-align: center;
position: relative;
animation: fadein 1s;
animation-timing-function: ease-out;
}
.img-container img {
width: 100%;
transition: width ease-in 0.15s;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.img-container:hover img {
width: 95%;
transition: width ease-in 0.15s;
}
<div class="container">
<div class="box">
<div class="img-container">
<img src="http://via.placeholder.com/800x800?text=1">
</div>
</div>
<div class="box">
<div class="img-container">
<img src="http://via.placeholder.com/800x800?text=2">
</div>
</div>
<div class="box">
<div class="img-container">
<img src="http://via.placeholder.com/800x800?text=3">
</div>
</div>
<div class="box">
<div class="img-container">
<img src="http://via.placeholder.com/800x800?text=4">
</div>
</div>
</div>
Example in this plunker.

You animate with transform: scale() instead. It will give you a much smoother animation and the other elements won't be affected.
.img-container img {
width: 100%;
transition: transform ease-in 0.15s;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.img-container:hover img {
transform: scale(.95);
}
Stack snippet
.container {
display: flex;
flex-wrap: wrap;
align-content: center;
}
.box {
display: flex;
flex-direction: column;
justify-content: center;
margin-top: 1.5%;
align-items: center;
margin-right: 2%;
flex: 0 1 48%;
}
.box:nth-of-type(2n) {
margin-right: 0;
}
.img-container {
text-align: center;
position: relative;
animation: fadein 1s;
animation-timing-function: ease-out;
}
.img-container img {
width: 100%;
transition: transform ease-in 0.15s;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.img-container:hover img {
transform: scale(.95);
}
<div class="container">
<div class="box">
<div class="img-container">
<img src="http://via.placeholder.com/800x800?text=1">
</div>
</div>
<div class="box">
<div class="img-container">
<img src="http://via.placeholder.com/800x800?text=2">
</div>
</div>
<div class="box">
<div class="img-container">
<img src="http://via.placeholder.com/800x800?text=3">
</div>
</div>
<div class="box">
<div class="img-container">
<img src="http://via.placeholder.com/800x800?text=4">
</div>
</div>
</div>

Related

Burger Menu Placement in Flexbox

I want to build a little note taking app but i cant figure out how i can put a burger menu on the right side of the flexbox. Down here you can find my js and css file:
JavaScript / HTML
<div className={styles.wrapper}>
<main className={styles.content}>
<div className={styles.templatelist}>
<div className={styles.template}>
<h2>Daily Meeting Minutes</h2>
<div className={styles.properties}>
<p>Sections: 5</p>
<p>Questions: 5</p>
<p>Tables: 5</p>
</div>
</div>
</div>
</main>
</div>
I have tried to create a new div and position it with top and left but nothing seems to work for me.
CSS
.wrapper {
display: flex;
margin-top: 2rem;
}
.content {
display: flex;
flex-direction: column;
margin: auto;
width: 50%;
height: 100%;
}
.templatelist {
margin-top: 2rem;
display: flex;
flex-direction: column;
}
.template {
width: 100%;
height: 6rem;
border-radius: 1rem;
padding: 1rem;
background: rgba(255, 255, 255, 0);
border-radius: 16px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(13.3px);
-webkit-backdrop-filter: blur(13.3px);
border: 1px solid rgba(255,153,0, .5);
}
.properties {
display: flex;
flex-direction: row;
margin-top: 1rem;
gap: 2rem;
}
Codepen
https://codepen.io/Vylex/pen/ZERgxzm
Desired outcome
.template {
width: 100%;
height: 6rem;
border-radius: 1rem;
padding: 1rem;
background: rgba(255, 255, 255, 0);
border-radius: 16px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(13.3px);
-webkit-backdrop-filter: blur(13.3px);
border: 1px solid rgba(255,153,0, .5);
display: flex;
justify-content: space-between;
}
.properties {
display: flex;
flex-direction: column;
}
p {
margin: .5rem;
}
I recommend you do the following:
<div class="templatelist">
<div class="template">
<h2>Daily Meeting Minutes</h2>
<div class="properties">
<p>Sections: 5</p>
<p>Questions: 5</p>
<p>Tables: 5</p>
</div>
</div>
<div class="menu">Burger</div>
keep the border and everything in the templateList class. Use the display to flex, flex-direction to row, and justify-content to space-between. I believe this will work for you.
CSS and HTML
.wrapper {
display: flex;
margin-top: 2rem;
}
.content {
display: flex;
flex-direction: column;
margin: auto;
width: 50%;
height: 100%;
}
.templatelist {
margin-top: 2rem;
display: flex;
flex-direction: column;
}
.template {
width: 100%;
border-radius: 1rem;
padding: 1rem;
background: rgba(255, 255, 255, 0);
border-radius: 16px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(13.3px);
-webkit-backdrop-filter: blur(13.3px);
border: 1px solid rgba(255,153,0, .5);
}
.properties {
display: flex;
flex-direction: row;
gap: 2rem;
justify-content: space-between;
align-items: center;
}
.burger{
font-size: 2em;
}
.options{
display: flex;
column-gap: 1em;
}
<div class="wrapper">
<main class="content">
<div class="templatelist">
<div class="template">
<div class="properties">
<div class="left">
<h2>Daily Meeting Minutes</h2>
<div class="options">
<p>Sections: 5</p>
<p>Questions: 5</p>
<p>Tables: 5</p>
</div>
</div>
<div class="burger">
<p>:</p>
</div>
</div>
</div>
</div>
</main>
</div>

Control width transformation ( CSS )

I have some cards in a div and want them to change width on hover, but have two issues whith it:
I want to use transition , but the cards that are not hovered do transition after hovered card ends one. I want do it simultaneously.
How to change origin for 3rd and 4th card, so they change their width from right to left?
here is my code
body {
background-color: #333;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.cardBox {
width: 800px;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
background-color: rgb(200, 201, 202);
padding: 20px;
overflow: hidden;
}
.card {
height: 450px;
background-color: #fff;
width: 100%
}
.card:hover {
width: 450px;
transition: all 1s ease;
}
.card:hover~ :not(:hover) {
width: 100%;
transition: all 1s ease;
}
.card img {
width: 100%;
height: 90%;
}
.card span {
text-transform: uppercase;
color: rgb(41, 40, 40);
font-weight: 600;
letter-spacing: 1.2px;
font-size: 20px;
display: block;
text-align: center;
line-height: 30px;
}
<div class="cardBox">
<div class="card">
<!-- <img src="/1.jpg" alt=""> -->
<span>CSS</span>
</div>
<div class="card">
<!-- <img src="/3.jpg" alt=""> -->
<span>image</span>
</div>
<div class="card">
<!-- <img src="/2.jpg" alt=""> -->
<span>hover</span>
</div>
<div class="card">
<!-- <img src="/4.jpg" alt=""> -->
<span>effect</span>
</div>
</div>
body {
background-color: #333;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.cardBox {
width: 800px;
display: flex;
gap: 20px;
background-color: rgb(200, 201, 202);
padding: 20px;
overflow: hidden;
}
.card {
height: 450px;
background-color: #fff;
width: 100%;
flex: 1;
}
.card:hover {
width: 450px;
transition: all 1s ease;
flex: 4;
}
.card:hover~ :not(:hover) {
width: 100%;
transition: all 1s ease;
}
.card img {
width: 100%;
height: 90%;
}
.card span {
text-transform: uppercase;
color: rgb(41, 40, 40);
font-weight: 600;
letter-spacing: 1.2px;
font-size: 20px;
display: block;
text-align: center;
line-height: 30px;
}
<div class="cardBox">
<div class="card">
<!-- <img src="/1.jpg" alt=""> -->
<span>CSS</span>
</div>
<div class="card">
<!-- <img src="/3.jpg" alt=""> -->
<span>image</span>
</div>
<div class="card">
<!-- <img src="/2.jpg" alt=""> -->
<span>hover</span>
</div>
<div class="card">
<!-- <img src="/4.jpg" alt=""> -->
<span>effect</span>
</div>
</div>
The problem was grid display and wrong css selector (.card:hover~ :not(:hover)). Also, use transition in the selector not in :hover selector.
body {
background-color: #333;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.cardBox {
width: 800px;
/* display: grid;
grid-template-columns: repeat(4, 1fr); */
display: flex;
gap: 20px;
background-color: rgb(200, 201, 202);
padding: 20px;
overflow: hidden;
}
.card {
height: 450px;
background-color: #fff;
/* width: 100% */
width: 25%;
transition: all 1s ease;
}
.card:hover {
width: 450px;
/* transition: all 1s ease; */
}
/* .card:hover~ :not(:hover) {
width: 100%;
transition: all 1s ease;
} */
.card img {
width: 100%;
height: 90%;
}
.card span {
text-transform: uppercase;
color: rgb(41, 40, 40);
font-weight: 600;
letter-spacing: 1.2px;
font-size: 20px;
display: block;
text-align: center;
line-height: 30px;
}
<div class="cardBox">
<div class="card">
<!-- <img src="/1.jpg" alt=""> -->
<span>CSS</span>
</div>
<div class="card">
<!-- <img src="/3.jpg" alt=""> -->
<span>image</span>
</div>
<div class="card">
<!-- <img src="/2.jpg" alt=""> -->
<span>hover</span>
</div>
<div class="card">
<!-- <img src="/4.jpg" alt=""> -->
<span>effect</span>
</div>
</div>

When animation is done, how can we smooth out the transition

I am able to achieve smooth in and out effect using transform and transition. I was experimenting with animation but could not achieve smooth out effect.
The first example below works. Note that when you hover, the card will move. And when you no longer hover, the cards to the right will close in slowly.
The second example is the one I'm trying to improve. How can you make the cards close in slowly when using animation? Thanks in advance.
EXAMPLE 1
.container {
display: flex;
margin-top: 100px;
justify-content: center;
}
.card {
height: 200px;
width: 200px;
background-color: antiquewhite;
border: 1px solid black;
border-radius: 15px;
box-shadow: 1px 1px 15px 1px;
display: flex;
justify-content: center;
align-items: center;
transition: 1s;
}
.card:not(:first-child) {
margin-left: -150px;
}
.card:hover {
transform: translateY(-20px);
}
.card:not(:last-child):hover ~ .card {
transform: translateX(170px);
}
<div class="container">
<div class="card">
CARD
</div>
<div class="card">
CARD
</div>
<div class="card">
CARD
</div>
<div class="card">
CARD
</div>
<div class="card">
CARD
</div>
</div>
EXAMPLE 2
.container2 {
display: flex;
justify-content: center;
margin-top: 200px;
}
.tile {
height: 200px;
width: 200px;
background-color: antiquewhite;
border: 1px solid black;
border-radius: 15px;
box-shadow: 1px 1px 15px 1px;
display: flex;
justify-content: center;
align-items: center;
}
.tile:not(:first-child) {
margin-left: -150px;
}
.tile:not(:last-child):hover ~ .tile {
animation: slide 0.8s linear forwards;
}
#keyframes slide {
0% {
transform: translateX(0px);
}
100% {
transform: translateX(170px);
}
}
.tile:hover {
animation: float 0.8s forwards;
}
#keyframes float {
0% {
transform: translateY(0px);
}
100% {
transform: translateY(-15px);
}
}
<div class="container container2">
<div class="tile">
CARD
</div>
<div class="tile">
CARD
</div>
<div class="tile">
CARD
</div>
<div class="tile">
CARD
</div>
<div class="tile">
CARD
</div>
</div>
hi in the tile class you should add an animation like this:
.tile {
height: 200px;
width: 200px;
background-color: antiquewhite;
border: 1px solid black;
border-radius: 15px;
box-shadow: 1px 1px 15px 1px;
display: flex;
justify-content: center;
align-items: center;
animation-duration: 0.8s;}

CSS make card the same height running React and Bootstrap

I am using the Bootstrap 4 in React. Currently, the card for Item 1 is shorter than Item 2, but I want both the cards to have the same height.
I am expected to have more cards added to the bottom in the future.
My CSS file:
.CountryDetail {
width: 70%;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-left: 15%;
margin-right: 15%;
}
.cards {
background: #fcfcfc;
margin: 20px 40px;
transition: 0.4s all;
width: 800px;
padding: 20px;
margin-left: auto;
margin-right: auto;
}
.icon-size {
font-size: 50px;
}
.shadow-1 {
position: relative;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 0;
box-sizing: border-box;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.13);
}
.shadow-1:hover {
z-index: 1;
box-shadow: 0 8px 50px rgba(0, 0, 0, 0.2);
transform: scale(1.05);
transition: all 0.5s ease;
}
.vertical-center {
justify-content: center;
}
.show-hover {
opacity: 0;
transform: translateX(-20px);
transition: 1s all;
}
.cards:hover .show-hover {
opacity: 1;
transform: translateX(0px);
color: blue;
}
.vertical-align {
display: flex;
align-items: center;
}
My JavaScript file:
<div className="CountryDetail">
<div className="cards shadow-1 container">
<div className="row vertical-align">
<div className="col-2 text-center">
<FontAwesomeIcon className="icon-hover icon-size" icon={faPlane} color="#A9A9A9" />
</div>
<div className="col-8">
<h3>Item 1</h3>
</div>
<div className="col-2 text-center">
<FontAwesomeIcon className="show-hover icon-size" icon={faArrowRight} color="#A9A9A9" />
</div>
</div>
</div>
<div className="cards shadow-1 container">
<div className="row vertical-align">
<div className="col-2 text-center">
<FontAwesomeIcon className="icon-hover icon-size" icon={faHeart} color="#A9A9A9" />
</div>
<div className="col-8">
<h3>Item 2</h3>
<span>Under Construction...</span>
<h2>Testing</h2>
</div>
<div className="col-2 text-center">
<FontAwesomeIcon className="show-hover icon-size" icon={faArrowRight} color="#A9A9A9" />
</div>
</div>
</div>
</div>
I have tried to add line-height or height in CSS for cards class, but it would mess up the height of the contents inside the card.
If I modify my "cards" class like this by adding min-height:
.cards {
min-height: 200px;
background: #fcfcfc;
margin: 20px 40px;
transition: 0.4s all;
width: 800px;
padding: 20px;
margin-left: auto;
margin-right: auto;
}
I would get this:
Based on your need of the same height and centered content, update your CSS to:
.cards {
display: flex;
flex-direction: column;
justify-content: center;
min-height: 200px;
background: #fcfcfc;
margin: 20px 40px;
transition: 0.4s all;
width: 800px;
padding: 20px;
margin-left: auto;
margin-right: auto;
}
If you set the card to be display flex, since you have only one direct child (row), you can center that vertically.

Grid Element expand animations using CSS

I have the following
setTimeout(function(){
var sections = document.querySelectorAll('section'), main = document.querySelector('.grid-container'),
//section = sections[Math.floor(Math.random() * 3)];
section = sections[1];
section.classList.add('expand');
section.parentElement.classList.add('expand');
main.classList.add('expanding');
}, 2000);
*{
box-sizing : border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.grid-container {
width:100%;
height: 100vh;
display:flex;
border: 1px solid;
flex-wrap: wrap;
flex-direction: column;
}
.grid-row, .grid-container {
overflow:hidden;
}
.grid-column, .grid-row {
display: flex;
transition: width .2s, height .2s, margin .2s, transform .2s;
}
.grid-column {
width: inherit;
height: inherit;
align-items: center;
justify-items: center;
}
.grid-column:nth-child(1) {
background-color:green;
}
.grid-column:nth-child(2) {
background-color:orange;
}
.grid-row:nth-child(2) .grid-column:nth-child(1) {
background-color:violet;
}
.grid-row:nth-child(2) .grid-column:nth-child(2) {
background-color:brown;
}
#media screen and (orientation: portrait) {
.grid-row {
width: 100%;
height: 50%;
flex-direction: column;
}
.grid-column {
width: 100%;
height: 50%;
}
.grid-row.expand .grid-column {
transform: translateY(-50%);
}
}
#media screen and (orientation: landscape) {
.grid-row {
width: 50%;
height: 100%;
}
.grid-column {
width: 50%;
height: 100%;
}
}
#media screen and (min-height: 500px) {
.grid-row {
height: 50%;
width: 100%;
}
}
.expanding .expand {
width: 100% !important;
height: 100% !important;
}
<main class="grid-container">
<div class="grid-row" data-index="1">
<section class="grid-column" data-index="1">
<article>
<p>
1
</p>
</article>
</section>
<section class="grid-column" data-index="2">
<article>
<p>
2
</p>
</article>
</section>
</div>
<div class="grid-row" data-index="2">
<section class="grid-column" data-index="1">
<article>
<p>
3
</p>
</article>
</section>
<section class="grid-column" data-index="2">
<article>
<p>
4
</p>
</article>
</section>
</div>
</main>
that I'm trying to develop where the "cells" in the grid that when expands to full area of the view will animate to as if its "pushing" the adjacent elements out of the view.
I'm trying to use a combination of width, height and transforms to give the appropriate animation but the transforms seem to give some unexpected results...
Is there a way to accomplish this WITHOUT position:absolute or with as little javascript as possible??
Here's an example seemingly doing what you want, coded from scratch, without any JavaScript. I used flexbox instead of grid, but it can be achieved with grid as well. I used :hover as a trigger:
body {
padding: 15px;
background-color: #999;
margin: 0;
}
.grid>*:hover,
.grid>*>*:hover {
flex-grow: 3;
}
.grid>*>*:hover {
box-shadow: 0 4px 5px -2px rgba(0, 0, 0, .2), 0 7px 10px 1px rgba(0, 0, 0, .14), 0 2px 16px 1px rgba(0, 0, 0, .12);
z-index: 1;
opacity: 1;
font-size: 5rem;
}
.grid:hover>*:not(:hover) {
flex-grow: 0;
max-height: 0;
overflow: hidden;
}
.grid>*,
.grid>*>* {
transition: all .6s cubic-bezier(0.5, 0, 0.3, 1);
}
.grid {
flex-direction: column;
min-height: calc(100vh - 30px);
box-sizing: border-box;
}
.grid,
.grid>* {
display: flex;
max-height: 100%;
}
.grid>* {
flex-direction: row;
margin: 0;
}
.grid>*,
.grid>*>* {
flex-grow: 1;
}
.grid>*>* {
margin: 0;
z-index: 0;
position: relative;
background-color: #fff;
outline: 1px solid #ddd;
opacity: .95;
display: flex;
align-items: center;
justify-content: center;
line-height: 0;
font-size: 3rem;
overflow: hidden;
}
<div class="grid">
<div>
<div>1</div>
<div>2</div>
</div>
<div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
<div>
<div>7</div>
<div>8</div>
<div>9</div>
</div>
</div>
You can play around with flex-grow, change animation or the ratio between hovered and non-hovered elements but, for that, you need to define the requirements better than "seem to give some unexpected results":
You can obviously limit it to 2 + 2 elements. I just wanted to point out it's flexible in terms of structure. Here's an example, expanding to full on both vertical and horizontal:
body {
padding: 15px;
background-color: #999;
margin: 0;
}
.grid>*:hover,
.grid>*>*:hover {
flex-grow: 3;
}
.grid>*>*:hover {
box-shadow: 0 4px 5px -2px rgba(0, 0, 0, .2), 0 7px 10px 1px rgba(0, 0, 0, .14), 0 2px 16px 1px rgba(0, 0, 0, .12);
z-index: 1;
opacity: 1;
font-size: 5rem;
}
.grid:hover>*:not(:hover) {
flex-grow: 0;
max-height: 0;
overflow: hidden;
}
.grid>*:hover>*:not(:hover) {
flex-grow: 0;
flex-basis: 0;
overflow: hidden;
}
.grid>*,
.grid>*>* {
transition: all .6s cubic-bezier(0.5, 0, 0.3, 1);
}
.grid {
flex-direction: column;
min-height: calc(100vh - 30px);
box-sizing: border-box;
}
.grid,
.grid>* {
display: flex;
max-height: 100%;
}
.grid>* {
flex-direction: row;
margin: 0;
}
.grid>*,
.grid>*>* {
flex-grow: 1;
}
.grid>*>* {
margin: 0;
z-index: 0;
position: relative;
background-color: #fff;
outline: 1px solid #ddd;
opacity: .95;
display: flex;
align-items: center;
justify-content: center;
line-height: 0;
font-size: 3rem;
overflow: hidden;
max-width: 100%;
flex-basis: 100%;
flex-grow: 0;
}
<div class="grid">
<div>
<div>1</div>
<div>2</div>
</div>
<div>
<div>3</div>
<div>4</div>
</div>
</div>
Generally, I'd avoid going full width/full height, as it makes selecting another item way more difficult.

Resources