css overlay: how do I maintain "relative" position on a "fixed" element? - css

I have a simple css/js animation that I have styled with 'position: fixed' attribute so that it overlays other elements on the page.
However, I still want the animation to position itself relative to other elements and while this appears to work OK on a full-width page, it goes awry on mobile layouts.
Here's a quick example: https://codepen.io/Megistus/pen/poLGbyL
body{
background-color: yellow;
}
.body-sw {
background-color: none;
height: 20vh;
display: block;
//align-items: center;
justify-content: center;
position: fixed;
top: 3%;
left: 0;
right: 0;
bottom: 0;
}
.sound-wave {
height: 20vh;
display: flex;
align-items: center;
//justify-content: center;
position: absolute;
top: 3%;
left: 0;
right: 0;
bottom: 0;
}
.body-sw .bar {
animation-name: wave-lg;
animation-iteration-count: 3;
animation-timing-function: ease-in-out;
animation-direction: alternate;
background: #006565;
margin: 0 1.5px;
height: 10px;
width: 1px;
}
.body-sw .bar:nth-child(-n+7), .body-sw .bar:nth-last-child(-n+7) {
animation-name: wave-md;
}
.body-sw .bar:nth-child(-n+3), .body-sw .bar:nth-last-child(-n+3) {
animation-name: wave-sm;
}
#keyframes wave-sm {
0% {
opacity: 0.35;
height: 10px;
}
100% {
opacity: 1;
height: 25px;
}
}
#keyframes wave-md {
0% {
opacity: 0.35;
height: 15px;
}
100% {
opacity: 1;
height: 50px;
}
}
#keyframes wave-lg {
0% {
opacity: 0.35;
height: 15px;
}
100% {
opacity: 1;
height: 70px;
}
}
(excuse the messy css, there's a lot of unnecessary guff in there!)
As you can see, I'm hoping got the animation to maintain its position between the "LOGO" div above and the "content" div below, but for the expanded "bars" in the animation to overlay the elements above and below it when the animation plays (on page load).
Is there a way to do this?

You actually do not want to use position: fixed;. This will forced the element to a fixed position on the page.
Instead, you can set position: absolute;, which will give you what seems to be the same result, however if you modify your HTML a little, you can get the animation to stay with the logo.
You need to place the animation elements inside of a container that holds both the logo and the animation. Then if you set this parent container to position: relative; now your animation elements will stay with the logo and the position: absolute; you set will allow the animation to overlay the logo still.
window.addEventListener("load", () => {
const bar = document.querySelectorAll(".bar");
for (let i = 0; i < bar.length; i++) {
bar.forEach((item, j) => {
// Random move
item.style.animationDuration = `${Math.random() * (0.7 - 0.2) + 0.2}s`; // Change the numbers for speed / ( max - min ) + min / ex. ( 0.5 - 0.1 ) + 0.1
});
}
});
body{
background-color: yellow;
}
.logo { position: relative; }
.body-sw {
background-color: none;
height: 20vh;
display: block;
//align-items: center;
justify-content: center;
position: absolute;
top: -.5em;
left: -.5em;
right: 0;
bottom: 0;
}
.sound-wave {
height: 20vh;
display: flex;
align-items: center;
//justify-content: center;
}
.body-sw .bar {
animation-name: wave-lg;
animation-iteration-count: 3;
animation-timing-function: ease-in-out;
animation-direction: alternate;
background: #006565;
margin: 0 1.5px;
height: 10px;
width: 1px;
}
.body-sw .bar:nth-child(-n+7), .body-sw .bar:nth-last-child(-n+7) {
animation-name: wave-md;
}
.body-sw .bar:nth-child(-n+3), .body-sw .bar:nth-last-child(-n+3) {
animation-name: wave-sm;
}
#keyframes wave-sm {
0% {
opacity: 0.35;
height: 10px;
}
100% {
opacity: 1;
height: 25px;
}
}
#keyframes wave-md {
0% {
opacity: 0.35;
height: 15px;
}
100% {
opacity: 1;
height: 50px;
}
}
#keyframes wave-lg {
0% {
opacity: 0.35;
height: 15px;
}
100% {
opacity: 1;
height: 70px;
}
}
<br>
<br>
<br>
<div class="logo">
<h1>LOGO</h1>
<div class="body-sw">
<div class='sound-wave'>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
<div class='bar'></div>
</div>
</div>
</div>
<div>
<h1>Content....</h1>
</div>

Related

CSS animation rotation issue

I have an animated infinite auto-scrolling carrousel. The tiles of the carrousel ares tilted to transform:rotateX(45deg) but they revert to 0deg because the animation for auto-scrolling has its own transform:. Since the animation is a loop I want the tiles to stay at a fixed rotation so there is no stutter through each loop.
.slider {
background: none;
height: 600px;
margin: auto;
overflow:hidden;
position: relative;
display: flex;
align-items: center;
width: 100%;
}
.slider::before,
.slider::after {
content: "";
height: 100px;
position: absolute;
width: 200px;
z-index: 2;
}
.slide-track {
animation: scroll 5s linear infinite;
display: flex;
width: calc(300px * 14);
perspective: 9000px;
}
#keyframes scroll {
0% { transform: translateX(0); }
100% { transform: translateX(calc(-300px * 7))}
}
.slide {
width: 300px;
height: 500px;
background-color: #17141d;
margin-left: 30px;
transform: rotateX(45deg) scale(0.8);
border-radius: 10px;
box-shadow: -1rem 0 3rem #000;
display: flex;
justify-content: center;
overflow: hidden;
flex-direction: column;
align-items: center;
}
<div class="slider">
<div class="slide-track">
<div class="slide" ></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
<div class="slide"></div>
</div>
</div>
The transform property accepts multiple values simultaneously. In your case, change the keyframes declaration to this:
#keyframes scroll {
0% { transform: translateX(0) rotateX(45deg) scale(0.8); }
100% { transform: translateX(calc(-300px * 7)) rotateX(45deg) scale(0.8); }
}

How to have 3 #keyframes fill's on the same page?

I am trying to get three keyframes to work independently from each other
I have added some HTML and CSS on a friends codepen account to show you.
https://codepen.io/williamharvey/pen/JjJjRdz
I have three circular dials that have the following.
.circle-wrap .circle .fill {
animation: fill ease-in-out 3s;
transform: rotate(45deg);
}
#keyframes fill {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(45deg);
}
}
But I want the second dial to be 65deg
.circle-wrap .circle .fill {
animation: fill ease-in-out 3s;
transform: rotate(65deg);
}
#keyframes fill {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(65deg);
}
}
and the third 95deg
.circle-wrap .circle .fill {
animation: fill ease-in-out 3s;
transform: rotate(95deg);
}
#keyframes fill {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(95deg);
}
}
Is this even possible?
Thanks in advance.
short answser: Yes.
You can use the forwards (keyword) to freeze your animation on its ending value, and CSS var() to apply specific values from different elements but from a single rule :
example from your code :
.circle-wrap {
margin: 50px auto;
width: 240px;
height: 240px;
background: #e5e5e5;
border-radius: 50%;
transform: rotate(-125deg);
}
.circle-wrap .circle .mask,
.circle-wrap .circle .fill {
width: 240px;
height: 240px;
position: absolute;
border-radius: 50%;
}
.circle-wrap .circle .mask {
clip: rect(0px, 240px, 240px, 120px);
}
.circle-wrap .circle .mask .fill {
clip: rect(0px, 120px, 240px, 0px);
background-color: #ffe100;
}
.circle-wrap .circle .mask.full,
.circle-wrap .circle .fill {
animation: fill ease-in-out 3s forwards;
}
#keyframes fill {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate( var(--rt));
}
}
.circle-wrap .inside-circle {
width: 185px;
height: 185px;
border-radius: 50%;
background: #fff;
line-height: 185px;
text-align: center;
top: 28px;
left: 28px;
z-index: 100;
font-weight: 700;
font-size: 6.5rem;
letter-spacing: -4px;
transform: rotate(114deg);
font-style: italic;
font-family: brandon-grotesque;
padding: 0;
position: relative;
}
.circle-wrap .inside-circle span {
font-size: 2.5rem;
letter-spacing: 0;
}
.circle-wrap .inside-circle .cone {
width: 0;
height: 0;
border-left: 175px solid transparent;
border-right: 175px solid transparent;
border-top: 125px solid white;
border-radius: 50%;
transform: rotate(192deg);
position: absolute;
bottom: -33px;
left: -96px;
z-index: -1;
}
.circle-wrap .inside-circle .cone .dial-speeds {
transform: rotate(179deg);
position: relative;
z-index: 1;
font-weight: 400;
font-style: normal;
}
.circle-wrap .inside-circle .cone .dial-speeds .left {
position: absolute;
bottom: -78px;
width: 18px;
height: 20px;
left: -50px;
}
.circle-wrap .inside-circle .cone .dial-speeds .right {
position: absolute;
bottom: -78px;
width: 18px;
height: 20px;
right: -50px;
}
.circle-wrap .inside-circle .cone .dial-speeds .right span {
right: -16px;
top: -58px;
position: absolute;
font-size: 15px;
}
.circle-wrap .inside-circle .cone .dial-speeds .left span {
left: -16px;
top: -58px;
position: absolute;
font-size: 15px;
}
<div class="grid gap-4 grid-cols-3 text-left pt-24">
<div class="circle-wrap">
<div class="circle">
<div class="mask full">
<div class="fill fill"></div>
</div>
<div class="mask half">
<div class="fill fill" style="--rt:45deg"></div>
</div>
<div class="inside-circle">
300<span></span>
<div class="cone">
<div class="dial-speeds">
<div class="left">
<img src="">
<span>300</span>
</div>
<div class="right">
<img src="">
<span>100</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="circle-wrap">
<div class="circle">
<div class="mask full">
<div class="fill"></div>
</div>
<div class="mask half">
<div class="fill" style="--rt:60deg"></div>
</div>
<div class="inside-circle">
500<span></span>
<div class="cone">
<div class="dial-speeds">
<div class="left">
<img src="">
<span>500</span>
</div>
<div class="right">
<img src="">
<span>200</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="circle-wrap">
<div class="circle">
<div class="mask full">
<div class="fill" style="--rt:95deg"></div>
</div>
<div class="mask half">
<div class="fill"></div>
</div>
<div class="inside-circle">
900<span></span>
<div class="cone">
<div class="dial-speeds">
<div class="left">
<img src="">
<span>900</span>
</div>
<div class="right">
<img src="">
<span>300</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Ressources :
https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode look at forwards
https://developer.mozilla.org/en-US/docs/Web/CSS/var()

Overlaying multiple div pictures

So I am trying to make a loop of images that has description overlaying each of it. The overlay would be visible when the picture is hovered. Here is an example of the code.
.container {
height: 100px;
width:100px;
display: inline-block;
}
.picture {
height: 100%;
width:100%
}
.contAlign {
text-align: center;
}
.desc {
position:flex;
bottom: 0;
left: 0;
right: 0;
background-color: black;
width: 100%;
height: 0%;
opacity: 0.5;
transition: .5s ease;
}
.container:hover .desc {
height: 40%;
}
<div class="contAlign">
<div class="container">
<img class="picture" src="https://kbob.github.io/images/sample-3.jpg">
<div class="desc"></div>
</div>
<div class="container">
<img class="picture" src="https://imagej.nih.gov/ij/images/baboon.jpg">
<div class="desc"></div>
</div>
<div class="container">
<img class="picture" src="https://www.visioncritical.com/wp-content/uploads/2014/12/BLG_Andrew-G.-River-Sample_09.13.12.png">
<div class="desc"></div>
</div>
</div>
In this case, the description box goes downwards since I wasnt using position: absolute;. However if I do so, the box wont inherit the pictures size and takes the size of the page. How do I solve this?
FIDDLE
Set the position of container to relative so the description would be absolute in relation to it:
.container {
height: 100px;
width:100px;
display: inline-block;
position:relative;
}
.picture {
height: 100%;
width:100%
}
.contAlign {
text-align: center;
}
.desc {
position:absolute;
bottom: 0;
left: 0;
right: 0;
background-color: black;
width: 100%;
height: 0%;
opacity: 0.5;
transition: .5s ease;
}
.container:hover .desc {
height: 40%;
}
<div class="contAlign">
<div class="container">
<img class="picture" src="https://kbob.github.io/images/sample-3.jpg">
<div class="desc"></div>
</div>
<div class="container">
<img class="picture" src="https://imagej.nih.gov/ij/images/baboon.jpg">
<div class="desc"></div>
</div>
<div class="container">
<img class="picture" src="https://www.visioncritical.com/wp-content/uploads/2014/12/BLG_Andrew-G.-River-Sample_09.13.12.png">
<div class="desc"></div>
</div>
</div>
I hope this helps you out. once you make an element absolute, just make sure to make its parent relative. so that it doesn't float anywhere. Now you can set positions accordingly where you want to make it appear on hover.
.container {
height: 100px;
width:100px;
display: inline-block;
position: relative;
}
.picture {
height: 100%;
width:100%
}
.contAlign {
text-align: center;
}
.desc {
position:absolute;
bottom: 0;
left: 0;
right: 0;
background-color: black;
width: 100%;
height: 0%;
opacity: 0.5;
transition: .5s ease;
}
.container:hover .desc {
height: 40%;
}
<div class="contAlign">
<div class="container">
<img class="picture" src="https://kbob.github.io/images/sample-3.jpg">
<div class="desc"></div>
</div>
<div class="container">
<img class="picture" src="https://imagej.nih.gov/ij/images/baboon.jpg">
<div class="desc"></div>
</div>
<div class="container">
<img class="picture" src="https://www.visioncritical.com/wp-content/uploads/2014/12/BLG_Andrew-G.-River-Sample_09.13.12.png">
<div class="desc"></div>
</div>
</div>

Evenly distribute scaled items?

How can I modify the styles below to result in the elements having the same spacing between each after the scaling? (without absolutely positioning them)
Desired Result:
.menu-next, .menu-previous1 {
transform: scale(.9); transform-origin: left;
}
.menu-previous2 { transform: scale(.7); transform-origin: left;}
.menu-previous3 { transform: scale(.55); transform-origin: left;}
.menu {
background-color: gray;
padding: 10px;
}
.menu div {
display: block;
width: 20%;
padding: 10px;
background-color: white;
color: green;
}
<div class="menu">
<div class="menu-previous3">Items</div>
<div class="menu-previous2">Store</div>
<div class="menu-previous1">Friends</div>
<div class="menu-current" >Settings</div>
<div class="menu-next" >Other</div>
</div>
Use scale(x, y) and not scale(value) + transform-origin
.menu-next,
.menu-previous1 {
transform: scale(.9, 1);
transform-origin: left;
}
.menu-previous2 {
transform: scale(.7, 1);
transform-origin: left;
}
.menu-previous3 {
transform: scale(.55, 1);
transform-origin: left;
}
.menu {
display: flex;
flex-direction: column;
justify-content: center;
background-color: gray;
padding: 10px;
}
.menu div {
display: block;
width: 20%;
padding: 10px;
background-color: white;
border: 1px solid green;
color: green;
}
<div class="menu">
<div class="menu-previous3">Items</div>
<div class="menu-previous2">Store</div>
<div class="menu-previous1">Friends</div>
<div class="menu-current">Settings</div>
<div class="menu-next">Other</div>
</div>
With thatthere is an other problem : scalling text. But you can fix that with pseudo-element (like here)
The best way is to wrap the scaling items and apply the other ui properties seperately of items to that wrapping div and then apply the scaling to the item inside it only.
Here is your code with this theory applied and a little change of padding and margin for equal spacing:
.itemwrapper .menu-next, .itemwrapper .menu-previous1 {
transform: scale(.9); transform-origin: left;
}
.itemwrapper .menu-previous2 { transform: scale(.7); transform-origin: left;}
.itemwrapper .menu-previous3 { transform: scale(.55); transform-origin: left;}
.menu {
background-color: gray;
padding: 10px;
}
.itemwrapper{
display: block;
width: 20%;
padding: 5px 10px;
margin:2px;
background-color: white;
color: green;
}
<div class="menu">
<div class="itemwrapper"><div class="menu-previous3">Items</div></div>
<div class="itemwrapper"><div class="menu-previous2">Store</div></div>
<div class="itemwrapper"><div class="menu-previous1">Friends</div></div>
<div class="itemwrapper"><div class="menu-current" >Settings</div></div>
<div class="itemwrapper"><div class="menu-next" >Other</div></div>
</div>
Hope this helps.
May be you can adjust it by hand ... Not really a good solution, but it is difficult to go any better.
.menu-next,
.menu-previous1 {
transform: scale(.9);
}
.menu-previous2 {
transform: scale(.7);
margin-bottom: -6px;
}
.menu-previous3 {
transform: scale(.55);
margin-bottom: -12px;
}
.menu {
background-color: gray;
padding: 10px;
}
.menu div {
display: block;
width: 20%;
padding: 10px;
background-color: white;
color: green;
transform-origin: left;
}
<div class="menu">
<div class="menu-previous3">Items</div>
<div class="menu-previous2">Store</div>
<div class="menu-previous1">Friends</div>
<div class="menu-current">Settings</div>
<div class="menu-next">Other</div>
</div>
Based a bit off this answer and sort of hack-y: https://stackoverflow.com/a/16388428/1204415
Wrap your scaled divs, resize the wrappers, and move the scaled divs with negative margins within the wrappers. scale() seems to also scale borders, margins, and padding.
HTML
<div class="menu">
<div class="wrap1">
<div class="item menu-previous3">Items</div>
</div>
<div class="wrap2">
<div class="item menu-previous2">Store</div>
</div>
<div class="item menu-previous1">Friends</div>
<div class="item menu-current" >Settings</div>
<div class="item menu-next" >Other</div>
</div>
CSS
.wrap1 {
height: 20px;
margin: 0;
overflow: hidden;
background-color: black;
}
.wrap2 {
height: 32px;
margin: -5px 0 0 0;
overflow: hidden;
background-color: blue;
}
.menu-next, .menu-previous1 {
transform: scale(.9); transform-origin: left;
}
.menu-previous2 { transform: scale(.7); transform-origin: left;}
.menu-previous3 { transform: scale(.55); transform-origin: left; margin: -8px 0 0 0; }
.menu {
background-color: gray;
padding: 10px;
}
.menu .item {
display: block;
outline:1px solid red;
width: 20%;
padding: 10px;
background-color: white;
color: green;
}
A pen: https://codepen.io/dmoz/pen/vmjybo

Alining flipping cards in CSS HTML

I am making images with text on flipping cards. I am trying to put them on the site so there would be about nine of them, each time three of them next to one another. Here is my code. Please just simply directly tell me how to implement it as I did not manage to fix the issue myself beforehand. I have no exp with HTML or CSS and just need a quick fix for the site. Thanks!
So the HTML bit in the end will be reproduced about nine times, the implementation has to be efficient for each copy.
<style> #f1_container {
position: margin-left;
margin: 10px;
width: 150%;
height: 150%;
z-index: 1;
}
#f1_container {
perspective: 1000;
}
#f1_card {
width: 113px;
height: 170px;
transform-style: preserve-3d;
transition: all 1.0s linear;
}
#f1_container:hover #f1_card {
transform: rotateY(180deg);
box-shadow: -5px 5px 5px #aaa;
}
.face {
position: absolute;
width: 150%;
height: 150%;
backface-visibility: hidden;
}
.face.back {
display: block;
transform: rotateY(180deg);
box-sizing: border-box;
padding: 10px;
color: white;
text-align: center;
background-color: #aaa;
}
</style>
<div id="f1_container">
<div id="f1_card" class="shadow">
<div class="front face">
<img src="http://img11.hostingpics.net/pics/714153square1.png"/>
</div>
<div class="back face center">
<p>TContent</p>
<p>Content</p>
</div>
.cardCont {
display: inline-block;
padding: 20px;
}
/*sets transition speed for the card flip you can change this*/
.Card {
height: 150px;
width: 150px;
border: 1px solid black;
transition: all .4s;
}
/*rotates on hover of outer div*/
.cardCont:hover .Card {
transform: rotateY(-180deg);
}
/*sets transitions for the front and back.. delay should half the transition this way this will only show when the card is half flipped*/
.Card .front,
.Card .back {
transition: all .1s;
transition-delay: .2s;
}
/*fixes the fact that this will now be backwards and hides it normally*/
.Card .back {
transform: rotateY(180deg);
display: none;
width: 100%;
}
/*following 2 set default properties for the front and back.*/
.cardCont:hover .Card .front {
display: none;
}
.cardCont:hover .Card .back {
display: inline-block;
}
<div class="cardCont">
<div class="Card">
<div class="front">Card1 Front
<br />you can put what you want in here.. this is the front</div>
<div class="back">Card1 Back
<br />you can put what you want in here.. this is the back</div>
</div>
</div>
<div class="cardCont">
<div class="Card">
<div class="front">Card2 Front
<br />you can put what you want in here.. this is the front</div>
<div class="back">Card2 Back
<br />you can put what you want in here.. this is the back</div>
</div>
</div>

Resources