CSS: Determine height of flip card in grid automatically without js - css

I would like to display two flip cards in a row using grid. Each of the flip cards shall contain a squared image on the front and some text on the back. How can I achieve not having to specify any height within the .flip-card css class? I would like the flip card to automatically adjust its height to the width of the image which itself is dependent on the overall space available within the grid (and therefore changes from device to device). At the moment I have to hardcode the height to make it work. But this inevitably leads the flip card not to be squared but to be a rectangle. Any ideas?
This is my code:
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 20px;
}
.flip-card {
position: relative;
background-color: transparent;
width: 100%;
height: 200px; /* This value should not be hard coded, but be set according to the width of the image which is determined by the grid. It should make the flip card a perfect square*/
overflow: hidden;
perspective: 1000px;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
transition: transform 0.6s;
transform-style: preserve-3d;
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.flip-card-front {
background-color: transparent;
}
.flip-card-back {
background-color: red;
transform: rotateY(180deg);
}
<div class="grid-container">
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png">
</div>
<div class="flip-card-back">
<p>
Some Text
</p>
</div>
</div>
</div>
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png">
</div>
<div class="flip-card-back">
<p>
Some Text
</p>
</div>
</div>
</div>
</div>

Don't use position:absolute to achieve this. Rely on CSS grid and make both the front and the back of the card on the same area so they overlap while still being in flow element so the area will be defined with the biggest height:
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 20px;
}
.flip-card {
overflow: hidden;
perspective: 1000px;
}
.flip-card-inner {
display: grid; /* here */
transition: transform 0.6s;
transform-style: preserve-3d;
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front,
.flip-card-back {
grid-area: 1/1; /*and here */
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.flip-card-back {
background-color: red;
transform: rotateY(180deg);
}
img {
max-width: 100%
}
<div class="grid-container">
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png">
</div>
<div class="flip-card-back">
<p>
Some Text
</p>
</div>
</div>
</div>
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png">
</div>
<div class="flip-card-back">
<p>
Some Text
</p>
</div>
</div>
</div>
</div>

Related

Flipping a card, CSS animation for web app

I've managed to build a card in React with a front and backside and have it flip successfully on hover with CSS. However, I want to flip it on click/touch.
I tried setting the transform property to a class and toggling that class on click but no luck.
How would you accomplish this?
This is how I am currently flipping it via hover:
.card {
position: relative;
perspective: 800px;
transition: transform 1s ease;
perspective: 1000px;
}
.card > * {
width: 10rem;
transition: transform 1s ease;
backface-visibility: hidden;
}
.card:hover > .card__front {
transform: rotateY(180deg);
}
.card:hover > .card__back {
transform: rotateY(0);
}
and my JSX
<div className={styles.card} >
{/* FRONTSIDE */}
<div className={styles.card__front}>
//FRONTSIDE CONTENT
</div>
{/* BACKSIDE */}
<div className={styles.card__back}>
//BACKSIDE CONTENT
</div>
</div>
UPDATE
This function works, it toggles the flip class on and off on my desired element. However, no animation happens once the class is added. The .flip class does the exact same thing as the :hover did though..
//function to toggle class
const flip = (element) => {
console.log(element);
element.classList.toggle("flip");
};
//the css class
.flip {
transform: rotateY(180deg);
}
You may use js to add a style to the element.
What you forgot to add is pretty simple, you forgot transition: transform 1s on the class and perspective: 1000px. The more less the more intense the effect is.
HTML:-
<link href="style.css" rel="stylesheet" type="text/css">
<script src="script.js"></script>
<div class="card-warpper">
<span onclick="flipCard()" class="card">
<div class="front">
Aye
</div>
<div class="back">
Bye
</div>
</span>
</div>
CSS:- (You will edit it based on your needs)
body {
background: blue;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
.card-warpper {
width: 50%;
height: 30%;
perspective: 1000px;
}
.card {
width: 100%;
height: 100%;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
transform-style: preserve-3d;
transition: transform 1s;
}
.card-clicked {
transform: rotateY(180deg);
}
.front {
backface-visibility: hidden;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
width: 100%;
height: 100%;
background-color: white;
color: black;
font-size: 2rem;
}
.back {
backface-visibility: hidden;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
width: 100%;
height: 100%;
background: black;
color: antiquewhite;
font-size: 2rem;
transform: rotateY(180deg);
}
Finally, JS:-
function flipCard() {
let card = document.getElementsByClassName("card")[0];
card.classList.toggle("card-clicked");
}
If this answer helped you, please dont hesitate to click the check mark beside it to accept the answer.
The problem was that React won't rerender the DOM when a class is added with the .toggle method.
The solution was to create a state out of the classlist and add the class from the classlist by using the setState method. This triggers a rerender
//JS
const [classlist, setClasslist] = useState(styles.card)
const flip = () => {
setClasslist(classlist + styles.flip)
}
//HTML
<div className={classlist} onClick={() => flip()}>
I'm still learning javascript but this is what i came up with...
I made a snippet using javascript, you can click the "card" and it goes to the back and when you "mouse out" it rotates back to front or if you comment out the second cards.forEach and you can click another card and it rotates back to front and the card you clicked rotates to the back.
I made a class called ".card__inner.is-flipped". With the "cards" variable declared in the javascript that targets all of the ".card__inner"'s i added and removed the ".is-flipped" class on "click" and "mouseleave" to each card.
let cards = document.querySelectorAll('.card__inner');
cards.forEach(el => {
el.addEventListener('click', function() {
cards.forEach(el => el.classList.remove('is-flipped'));
el.classList.add('is-flipped');
});
});
cards.forEach(el => {
el.addEventListener('mouseleave', function() {
cards.forEach(el => el.classList.remove('is-flipped'));
});
});
.cardRowWrapper { //RowWrapper CARD
display: flex;
flex-direction: row;
justify-content: space-evenly;
align-items: center;
flex-wrap: wrap;
width: 45rem;
height: 35rem;
perspective: 800px;
z-index: 100;
}
.card__inner { //Skills circle
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
height: 12rem;
width: 12rem;
border-radius: 50%;
background: green;
transition: transform 1s;
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
position: relative;
}
.card__inner.is-flipped {
transform: rotateY(180deg);
background: yellow;
}
.card__face {
position: absolute;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
-o-backface-visibility: hidden;
overflow: hidden;
}
.card__face--front {
display: flex;
backface-visibility: hidden;
align-items: center;
justify-content: center;
}
.card__face--back {
display: block;
transform: rotateY(180deg);
}
<div class="cardRowWrapper">
<div class="card__inner">
<div class="card__face card__face--front">
<p>This is the front</p>
</div>
<div class="card__face card__face--back">
<span class="skillsSubHeading">This is the back</span>
</div>
</div>
<div class="card__inner">
<div class="card__face card__face--front">
<p>This is the front</p>
</div>
<div class="card__face card__face--back">
<span class="skillsSubHeading">This is the back</span>
</div>
</div>
<div class="card__inner">
<div class="card__face card__face--front">
<p>This is the front</p>
</div>
<div class="card__face card__face--back">
<span class="skillsSubHeading">This is the back</span>
</div>
</div>
<div class="card__inner">
<div class="card__face card__face--front">
<p>This is the front</p>
</div>
<div class="card__face card__face--back">
<span class="skillsSubHeading">This is the back</span>
</div>
</div>
<div class="card__inner">
<div class="card__face card__face--front">
<p>This is the front</p>
</div>
<div class="card__face card__face--back">
<span class="skillsSubHeading">This is the back</span>
</div>
</div>
<div class="card__inner">
<div class="card__face card__face--front">
<p>This is the front</p>
</div>
<div class="card__face card__face--back">
<span class="skillsSubHeading">This is the back</span>
</div>
</div>
</div>

CSS div in bottom not showing if applied margin

I'm trying to achieve the following:
I was able to replicate the image but only if my div is not floating in the page (without the margin applied and without the position: absolute), otherwise I can't see the green rectangle.
My HTML structure is the following:
<div class="app">
<div class="interface">
<div class="view">
<div class="body">
<div class="top">
Top content
</div>
<div class="middle">
Middle content
</div>
<div class="bottom">
Bottom content
</div>
</div>
</div>
</div>
</div>
In the .interface CSS I have the following:
.interface
{
position: absolute;
top: 15%;
}
With this CSS I'm unable to see the green rectangle. If I remove the position: absolute (and therefore the top: 15% stops applying) I'm able to see the green rectangle.
You can see the issue in this JSFiddle: https://jsfiddle.net/v9euwdz3/
So, how do I manage to have the DIV showing at a certain level (margin from top) and without compromise my HTML structure?
Here is what you're trying to achieve using flex:
.body {
display: flex;
flex-direction: column;
background-color: blue;
justify-content: space-between;
height: 100vh;
}
.navetc {
background-color: white;
height: 15vh;
}
.top {
background-color: green;
height: 60px;
}
.middle {
background-color: yellow;
flex-grow: 1;
}
.bottom {
background-color: red;
height: 50px;
}
<div class="app">
<div class="interface">
<div class="view">
<div class="body">
<div class="navetc">
SPACE
</div>
<div class="top">
Top content
</div>
<div class="middle">
Middle content
</div>
<div class="bottom">
Bottom content
</div>
</div>
</div>
</div>
</div>
You could also use margin-top: 15%; instead of a placeholder div
.body {
display: flex;
flex-direction: column;
background-color: blue;
justify-content: space-between;
height: 100vh;
}
.top {
margin-top: 15vh;
background-color: green;
height: 60px;
}
.middle {
background-color: yellow;
flex-grow: 1;
}
.bottom {
background-color: red;
height: 50px;
}
<div class="app">
<div class="interface">
<div class="view">
<div class="body">
<div class="top">
Top content
</div>
<div class="middle">
Middle content
</div>
<div class="bottom">
Bottom content
</div>
</div>
</div>
</div>
</div>
(I used vh instead of % to get it to show up correctly in this code snippet)
as we know the content that have height which is 100% means is 100% of its parent and while the height of the parent is not defined will cause an error that's what you was stuck with you set the with of body to 100% but was not right you would set it to 100vh to fit the screen if you are on computer and the other mistakes that I found was in your calculation where you used to subtract the measurement which is in parcentages from the one in pixels height: calc(100% - 150px); and the others where simple mistakes
html,
body {
height: 100vh;
}
.app {
position: relative;
height: 100%;
display: flex;
}
.interface {
position: absolute;
height: 100%;
top: 15%;
}
.view {
position: fixed;
height: 100%;
background-color: #ccc;
width: 350px;
}
.body {
position: relative;
height: 100%;
}
.body .top {
height: 15%;
border: 1px solid #000;
}
.body .middle {
height: 60%;
border: 1px solid red;
}
.body .bottom {
height: 20%;
border: 1px solid green;
}
<div class="app">
<div class="interface">
<div class="view">
<div class="body">
<div class="top">
Top content
</div>
<div class="middle">
Middle content
</div>
<div class="bottom">
Bottom content
</div>
</div>
</div>
</div>
</div>
to see the result in the snippet you should observe it in full page and also when you see the result through jsfiddle there at the result section there is bar downward which hide some part of footer

how to verticall align divs with float:left?

I have this kind of structure....
<div class="container-fluid">
<div class="section_3 row">
<div class="image_info_carousel_left col-xs-12 col-sm-12 col-md-6 col-lg-6">
<h1>Stay organized with your personal moving dashboard</h1>
<div class="author">Get timely reminders and assign tasks to stay on top of your move</div>
</div>
<div class="info_image col-xs-12 col-sm-12 col-md-6 col-lg-6">
<img src="css/img/realtor-fourth.png" />
</div>
</div>
</div>
with this type of css....
.image_info_carousel_left {
padding: 100px 50px !important;
color: #fff;
background-color: #3B4C60;
}
.info_image {
padding: 0;
}
The height of the image within the image_info class varies dynamically... so the height of the image_info_carousel_left should also change & and the <h1> and <div class="author"> should be vertically centered...
I have tried using display:table & display:table-cell, but it doesn't work as classes with col-lg- are having float:left...
how can I do this?
this is the formula for vertical align anything.
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
Just put those commands to div you want to vertically align, or create a mixin if you are using preprocessors
I created this example to see it working with floats:
http://codepen.io/riogrande/pen/NxGROP
You can use display:inline-block; and vertical-align:middle; and don't forget to remove extra spaces which occurred by display:inline-block;.
Jsfiddle
* {
box-sizing: border-box;
}
.container {
width: 100%;
background: red;
padding: 10px;
}
.box {
display: inline-block;
vertical-align: middle;
width: 50%;
}
.box1 {
background: blue;
}
.box2 {
background: blue;
}
img {
width: 100%;
display: block;
}
<div class="container">
<div class="box1 box">
<img src="http://placehold.it/350x150">
</div><!--
--><div class="box2 box">heading with the fixed height</div>
</div>

3d cube rotation backwards text in div

I have a 3d cube rotation, that happens on hover. Everything works fine except one thing. When you roll over and the cube rotates showing a new side with text....the text is backwards, not sure why this is happening. I have a JS fiddle set up, and any help I can get on this would be great.
http://jsfiddle.net/c3ewZ/6/
html:
This is back
<div class='box-scene col-xs-12 col-sm-3'>
<div class='box'>
<div class='front face'></div>
<div class="side face">
<p>This is back</p>
</div>
</div>
</div>
<div class='box-scene col-xs-12 col-sm-3'>
<div class='box'>
<div class='front face'></div>
<div class="side face">
<p>This is back</p>
</div>
</div>
</div>
<div class='box-scene col-xs-12 col-sm-3'>
<div class='box'>
<div class='front face'></div>
<div class="side face">
<p>This is back</p>
</div>
</div>
</div>
css
body {
margin:0px;
padding:0px;
}
.box-scene {
-webkit-perspective: 700;
height: 180px;
float:left;
z-index: 999;
padding:0px !important;
}
.box-scene:hover .box {
-webkit-transform: rotateY(90deg);
}
.box {
width: 100%;
height: 100%;
position: relative;
-webkit-transform-style: preserve-3d;
-webkit-transition: all 0.4s ease-out;
-webkit-transform-origin: 90px 90px -90px;
}
.face {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: visible;
-webkit-transform-origin: 0 0;
}
.front {
-webkit-transform: rotateY(0deg);
z-index: 2;
background: #d9d9d9;
}
.side {
background: #9dcc78;
-webkit-transform: rotateY(90deg);
z-index: 1;
left: 0px;
}
JS
var resizer = function () {
var width = parseInt($(".box-scene").css("width"));
$(".box").css("-webkit-transform-origin", "center center -" + width / 2 + "px");
};
resizer();
$(window).resize(function () {
resizer();
});
Rotating the panel the other way will fix the mirror imaging of the text.
.box-scene:hover .box {
-webkit-transform: rotateY(-90deg);
}

Transform makes back side of 3D card unclickable

I want to make flip like http://desandro.github.io/3dtransforms/examples/card-01.html
But with buttons on each side. So here is my html
<div class="flip-container">
<div class="flip">
<div class="side front">
<p>front</p>
<button class="front-flip-button">flip</button>
</div>
<div class="side back">
<p>back</p>
<button class="back-flip-button">flip</button>
</div>
</div>
</div>
and css
.flip-container{
position: relative;
-webkit-perspective: 800;
width: 500px;
height: 300px;
}
.flip{
position: absolute;
width: inherit;
height: inherit;
-webkit-transform-style: preserve-3d;
-webkit-transition-duration: 500ms;
-webkit-transform: translate3d(0, 0, 0);
border: 1px solid;
}
.side{
position: absolute;
width: inherit;
height: inherit;
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
}
.flip.flipped,
.back{
-webkit-transform: rotate3d(0, 1, 0, 180deg);
}
.back-flip-button,
.front-flip-button{
position: absolute;
left: 0;
top: 0;
}
p{
font-size: 90px;
text-align: center;
}
And everything is pretty good, but when I use some element with translateZ it makes back button unclickable.
<div class="flip-container">
<div class="flip">
<div class="side front">
<p>front</p>
<button class="front-flip-button">flip</button>
</div>
<div class="side back">
<p>back</p>
<button class="back-flip-button">flip</button>
</div>
</div>
</div>
<div class="some"></div>
Why is that happening?
http://jsfiddle.net/j5Sm4/
Apply this
.back-flip-button {
... Your other styles ...
-webkit-transform:translateZ(1px);
-webkit-backface-visibility:hidden;
/* Needs other prefixes to be cross browser */
}
Demo
This is because the parent element gets its own stacking order. To equalize the stacking order and thus put the button on top, you have to give it a stacking order which I did using translateZ. The backface-visibility:hidden makes the button not show on the front side
In the future we will likely be able to do this by applying the will-change property to the back side

Resources