Stack Text on top of each other, multiply, then expand? - javascript

I'm attempting a project for myself, and I've found myself somewhat stuck.
I'm trying to make it so that text pushes onto the screen (from off screen), then bounces into the center. After reaching the center, it should expand into 3 (of the same text), while also fading in.
I don't know how to make something simultaneously fixed, and also move in line with an animation.
To be clear, I'm not talking about stacking things vertically -- I mean literally I would like the elements to appear as if they were one until the animation starts which separates & fades them in.
I'm sure there's some way to do this by simply multiplying the parent object, but I'm, admittedly, out of practice. Thus I'm trying to brute force it.
I've tried to use flexbox to make the objects fixed using position: fixed;, which is what I'm currently using. I also attempted keeping them all in the same flex container, which didn't work. Lastly, I tried just brute forcing it, but it doesn't work on every OS, so that's a no-go as well.
https://jsfiddle.net/4z203mxb/#&togetherjs=4o62tMyoEx
This is the CSS I'm using for the initial portion:
.nameContainer {
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
max-width: 1500px;
font-size: 7rem;
pointer-events: none;
position: relative;
animation: move1 4.25s ease 0s 1 forwards;
}
Which transitions into this when it "separates."
.nameContainerTwo {
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
max-width: 1500px;
font-size: 7rem;
pointer-events: none;
position: fixed;
animation: move2 3s ease 1.275s 1 forwards, delay 1.275s 0s 1, fade 2.275s ease-in-out 1.275s forwards;
This is what I've got thus far. (If I linked that incorrectly, apologies, I've never used it.)

Related

Why the sizes of those images are causing the layout shift? CSS? JavaScript?

https://codesandbox.io/s/stackoverflow2-bdiq2r
I really don't get it why the different sizes of the images are causing the layout shift. I wrote the code considering the difference in size of image for the responsive layout.
The problem is really strange that when you slide the carousel using the button on there, and the whole carousel is inside the viewport, there's no problem. But when you do slide it when part of the carousel is outside the viewport, that layout shift problem occurs.
I've been holding this bug for the whole day already, but really don't know why that size difference is causing the problem in this code, and how to make this work exactly as it is working when the whole carousel is inside the viewport. Is this my React code problem? or my CSS? There's no problem if I set height: 100% for .img but the way of this carousel working gets different.
I attach 2 images to describe the problem more intuitively.
As you can see the carousel gets moved down as soon as you slide to the image of different size (The only purple image has a different size).
It looks like this might be caused by align-items behavior when the images have different natural height.
In styles.module.css, try set align-items: stretch on .img-container and set object-fit: scale-down on .img to fix this.
Example: (with live demo on: codesandbox)
.img-container {
width: 100%;
display: flex;
justify-content: center;
/* 👇 Changed from 'center' to 'stretch' */
align-items: stretch;
text-align: center;
position: relative;
transform: skewY(0.001deg);
color: white;
font-weight: bold;
font-size: 2rem;
}
.img {
max-width: 100%;
max-height: 100%;
/* 👇 Changed from 'contain' to 'scale-down' */
object-fit: scale-down;
}

Container size doesn't shrink with child scale

I'm trying to create a custom drop down menu in ReactJs. When a user clicks the heading, a list of items appears below it. This works but I want the div that contains both the heading and the list (.db-container) to in increase its height depending on if the list (.db-list) is visible or not. I can use display:none/block or position:absolute/relative with transform:scaleY(0)/scaleY(1) on .db-list but then I cannot animate it or use transitions. I've tried using visibility:hidden/visible which does hide the list but the container remains its full size.
I am using ReactJs and in the code snippet below, the handleClick() function just changes isVisible from true to false and vice versa.
.db-container {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.db-list {
transform: scaleY(0);
transform-origin: top center;
position: absolute;
}
.visible-true {
transform: scaleY(1) !important;
position: relative !important;
}
<div className='db-container'>
<h3 className='db-name' onClick={handleClick}>Headinf</h3>
<ul className={`db-list visible-${isVisible}`}>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
</div>
Is there a way to get .db-container to change its height depending on the visibility of .db-list and use animations or transitions?
Use max-height and overflow:hidden. These are animatable. Needs a bit of tidying up but you'll get the general idea. Setting max-height means the element will just size itself to the content as long as you set it to a high enough value. (I've made it transform on :hover but you can change it to a click in react)
.db-container {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.db-list {
max-height:0px;
overflow: hidden;
transition: max-height 1s;
}
.db-name:hover + .db-list {
max-height:1000px;
}
Instead of shrinking, you can use position:absolute then delay your component from re-rendering when hiding for a few millisecond then animate.
I got this problem when I built a custom drawer menu. However, when I hide the component it doesn't animate because you can't animate what you can't see. So I had to delay the component re-render then set right to a negative number to move it out of the view port visible part with animation. After that hide the component.
If you use height(to hide by shrinking); it works, but for a second you will see the component children get misplace and it doesn't look great.

Can't center div on screen on top of page content after setting "display: block" on function using z-index?

I am currently building a blackjack game and was using alerts to let the player know they won. I eventually swapped over to using animate.css to get a simple "you won" and "you lost" message to appear on the screen after the logic finds a winner.
I do this by having a function popup() that runs each time a win or loss parameter is met within if elses, and sets the display to "block". At first, I had this animation div between the 2 sides of the game board ( the player and dealer side, each with a flex property), but hated the fact that once the div appears on the function running, it pushes the player side down. To fix this, I thought I could simply put a z-index to the animation so that it would just appear to overlap.
At first this wasnt working, but then I moved the div that holds my animation outside of the main container (which is a flex container), which now works and stops any content from being pushed down... but I am having issues with the positioning.
I am trying to position the div in the center of the screen to act as a modal or pop-up, and I want to add a interval the div to allow me to close the whole container when a timer runs out ( and thus remove the animation from the screen and allowing the player to choose the "new game" button ).
After trying various things, I can either...
get it to be centered ( H and V ), but pushing content ( meaning z index isnt working, which is where I started )
get it to have z-index and appear above everything else, and even get it to be centered in the screen, but unable to get its sizing to work properly and there is this weird UI glitch where the scrollbar will appear and then disappear ( as if the screen size is getting bigger when the animation appears, which is weird because the animation has a z-index of 2, so why would it make the screen bigger? ).
Sorry if this is a little hard to follow, but the TLDR is that I am unable to get my animation div to appear horizontally and vertically centered without some issue.
Here is some of my code:
<h1 class="animated jackInTheBox" id="youWin"></h1>
.jackInTheBox {
animation-duration: 4s;
animation-delay: 0s;
animation-iteration-count: 1;
margin: auto;
font-size: 32px;
position: relative;
z-index: 2;
margin: auto;
max-width: 100%;
text-align: center;
display: none;
background-color: teal;
}
This animation div sits inside of the main container div, at the very top
.mainContainer {
display: flex;
flex-direction: column;
width: auto;
height: auto;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
max-width: 100%;
max-height: 100%;
overflow: auto;
}
Part of me thinks that this would be better to do with a modal, but I would still like to see where I am going wrong. Thank you all in advance.
Try changing your jack in the box class to position fixed with
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -100px;
Like you mentioned, this is a little hard to follow without being able to see more code of what you have. Do you think you could add this as a jsfiddle/codepen that contains all of your code? I get a feeling there may be something more to the issue than what you have placed.
This link may also help https://css-tricks.com/quick-css-trick-how-to-center-an-object-exactly-in-the-center/
If parent container has position: relative and child has position: absolute then you can set children with following properties to move it in the middle of parent's horizontal and vertical axis:
.jackInTheBox {
animation-duration: 4s;
animation-delay: 0s;
animation-iteration-count: 1;
font-size: 32px;
z-index: 2;
text-align: center;
display: none;
background-color: teal;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Last four lines let you make it:
position: absolute; sets child in relation to parent's up, left corner (if parent has position: relative)
top: 50%; moves child to the center of screen (child's top border will be in the middle of screen horizontal axis)
left: 50%; moves child to the center of screen (child's left border will be in the middle of screen vertical axis)
transform: translate(-50%, -50%); makes child move 50% of its width into left and 50% of its height into top making it centered perfectly as you need
After doing this you don't need to set width neither max-width, as <h1> markup is a block element and it takes 100% of parent width automatically.
Additional, you don't have to make your parent element has display: relative to get the same effect. Child will use then screen original properties to set position.

Background-image suddenly disappears on certain screen sizes on Chrome

On my site I have a container in which numerous divs containing one i elements with background-images are rendered. Those i elements all have the same background-image but with different background-positions so that only one http request has to be made, which is general best practice for smaller icons. The divs should be horizontally centered in the container.
My problem is that on Chrome and Firefox browser (latest versions) the rendering of the background images is not working as intended on certain (wide) screen sizes. Specifically on Chrome it will always not show some of the elements background-image unless the element is hovered and on Firefox it will not render background images at all.
If I add float: left to the divs inside the container the rendering issue is solved. However I want to have the elements centered in the container which does not work with the float left.
My question is what am I doing which is causing this behaviour on certain browsers and how can I try to resolve it?
You can have a look at this problem for yourself on:
http://staging.koreanbuilds.net
Here is a screenshot of the behaviour on Chrome and on Firefox
This is the css code for the container and elements:
/* Container of clickable champion icons */
#champContainer {
width: 100%;
padding-right: 10px;
padding-left: 10px;
text-align: center;
position: relative;
}
/* Champion images div container class */
.champIcon {
width: 65px;
height: 65px;
margin: 1px auto;
overflow: hidden;
}
.champIcon i {
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
-ms-transition: all 0.3s ease;
}
.champIcon i:hover {
zoom: 1.05;
cursor: pointer;
-moz-transform:scale(1.05);
-moz-transform-origin: 0 0;
}
Additionally the divs have one of those two classes
.nodisplay {
display: none;
}
.yesdisplay {
display: inline-block;
}
The i elements always have the following class
.chmp {
display: inline-block;
overflow: hidden;
text-indent: -9999px;
text-align: left;
cursor: pointer;
}
as well as a class defining the background-image and position for example
.chmpashe {
background-image: url(http://statics.koreanbuilds.net/champion_65x65/sprite.png);
background-position: 0 -455px;
width: 65px;
height: 65px;
}
I don't see anything wrong with your code. It looks like this might be the same issue you are seeing here as I can't seem to load your spritesheet on it's own in Firefox
It might be worth cutting your sprite sheet down and testing if that works.
hope that helps!
edit:
Looking at your live site you have a more traditionally shaped stylesheet which doesn't go beyond 1000 pixels in ether dimension. It looks like the one you are using on staging goes beyond 80,000 pixels which looks to be where your issue is.

Transition elements below a transitioned v-if

I have two elements, and the top one's visibility is controlled by a v-if on a simple boolean.
transition(name="fade")
#element1(v-if="showFirst")
p Foo
#element2
p Bar
The first element is wrapped in a <transition> tag, exactly as per the Vue documentation.
However, while this does create a fading animation, the rest of the content on the page still jumps very jarringly.
How can I create a transition that will also smoothly transform the position of any and all siblings that follow?
A fiddle demoing this issue.
You need to use a transition-group and key your dynamic div and static div
<transition-group name="fade">
<div v-if="switc" key="dynamic" class="animated">
...
</div>
<div key="main-content" class="animated">
...
</div>
</transition-group>
And use this css classes
.fade-enter,
.fade-leave-active {
opacity: 0;
transform: translateY(-10px);
}
.fade-leave-active {
position: absolute;
}
.animated {
transition: all 0.5s;
/*display: flex;*/
width: 100%;
}
The real trick is to change position to absolute when leaving, then any other content can take correct position.
To know more about how Vue animate things please see this FLIP explanation post
And please see this working fiddle
https://jsfiddle.net/bjfhth7c/4/
Edit
By mistake I did set display: flex; in .animated class, that was causing to every inner element to render in a strange way.
So now, I completely remove .animate class, and instead apply transition: all 0.5s and width:100% to every direct inner element of .wrapper
My final scss looks like this:
.wrapper {
display: flex;
flex-direction: column;
>* {
transition: all 0.5s;
width:100%;
};
}
.fade-enter,
.fade-leave-active {
opacity: 0;
transform: translateY(-10px);
}
.fade-leave-active {
position: absolute;
}
Flex layout is a extend subject, but in short for this particular case flex-direction: column is arranging elements one bellows previous one.
If one of those elements has absolute position will be ignored in flex layout so any other elements will be redistributed on available space.
Please see this guide about flexbox and last working fiddle hope it helps.
You can use a slideDown/slideUp animation instead. For achieve this you don't need to know a height of a sliding element, the principles of max-height transition explained there.
So, as a result it will cause animated moving of elements below target.
Check out my example based on your fiddle.
vue js provides different transition classes, you have to use those properly to smooth the transition, I have tried with your example in this fiddle with some CSS, have a look.
.fade-enter-active, .fade-leave-active {
transition: all .5s;
height: 100px;
opacity: 0.5;
}
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
height: 0px;
opacity: 0;
}
Some details from documentation:
There are six classes applied for enter/leave transitions.
v-enter: Starting state for enter. Added before element is inserted, removed one frame after element is inserted.
v-enter-active: Active state for enter. Applied during the entire entering phase. Added before element is inserted, removed when transition/animation finishes. This class can be used to define the duration, delay and easing curve for the entering transition.
v-enter-to: Only available in versions >=2.1.8. Ending state for enter. Added one frame after element is inserted (at the same time v-enter is removed), removed when transition/animation finishes.
v-leave: Starting state for leave. Added immediately when a leaving transition is triggered, removed after one frame.
v-leave-active: Active state for leave. Applied during the entire leaving phase. Added immediately when leave transition is triggered, removed when the transition/animation finishes. This class can be used to define the duration, delay and easing curve for the leaving transition.
v-leave-to: Only available in versions >=2.1.8. Ending state for leave. Added one frame after a leaving transition is triggered (at the same time 7. v-leave is removed), removed when the transition/animation finishes.
You can as well use CSS animations where you can provide on different phases of transition what will be your css property to make your transitions more smooth, like following and demo fiddle:
.fade-enter-active {
animation: bounce-in .5s;
}
.fade-leave-active {
animation: bounce-out .5s;
}
#keyframes bounce-in {
0% {
height: 5px;
}
30% {
height: 30px;
}
50% {
height: 50px;
}
100% {
height: 100px;
}
}
#keyframes bounce-out {
0% {
height: 90px;
}
50% {
height: 50px;
}
100% {
height: 0px;
}
}

Categories