css transition not working correctly in vuejs - css

I am trying to animate the slide in/out of my flyout however it doesn't transition but appear and disappear in the same place.
in chrome devtools the animation works if I tick/untick right: 0;
How can I slide in/out the flyout correctly?
<template>
<portal to="modalPortal">
<div
v-if="isMoreOffersFlyoutActive"
:id="id"
class="flyOut"
#click.self="sendCloseModal(true)">
<div
:class="['flyOut__container', {'flyOut__container--active': isMoreOffersFlyoutActive}]">
<div class="flyOut__buttonContainer">
<button
id="storeInfoClose"
class="flyOut__button"
#click="sendCloseModal(false)">
<icon
:scale="closeButtonIconScale"
name="close"
color="white" />
</button>
</div>
<div class="flyOut__content">
<slot />
</div>
</div>
</div>
</portal>
</template>
.flyOut {
position: fixed;
top: 0;
left: 0;
z-index: z("overlay");
display: flex;
justify-content: flex-end;
width: 100%;
height: 100%;
overflow: auto;
background-color: $black-alpha;
&__container {
position: relative;
z-index: z("modal");
right: -50%;
width: 50%;
height: 100%;
background-color: $white;
box-shadow: -2px 0 15px 5px rgba(0,0,0,0.2);
transition: right ease 0.5s;
&--active {
right: 0;
transition: right ease 0.5s;
background: #ff00ff;
}
}

There isn't really an issue with Vue here. The problem stems from trying to animate a position between two different units (or in your case units and no units). Changing right: 0; to right: 10%; would probably work.
All that said, PLEASE don't animate CSS position. It's not performant and causes the browser to reflow & repaint stuff. The better solution is to use css translate(). Here's an example...
.wrapper {
/* need a positioned container for SO's editor */
position: fixed;
top:0; right:0; bottom:0; left:0;
overflow:hidden;
}
.action{
margin: 30px;
font-size: 18px;
font-weight: bold;
cursor:pointer;
font-family: sans-serif;
}
.moved{
position: absolute;
/* put the element where you want it */
top:0;
right:0;
bottom:0;
width: 150px;
background: #333;
padding: 20px;
color: #fff;
/* use transform to move to a new position (100% of element width) */
transform: translatex(100%);
transition: transform 0.5s cubic-bezier(.47,1.64,.41,.8);
}
.action:hover+.moved {
transform: translatex(0);
}
<div class="wrapper">
<div class="action">Hover Me</div>
<div class="moved">Transformed element</div>
</div>

Related

how to effect two Items hovering each others css? [duplicate]

This question already has answers here:
Is there a "previous sibling" selector?
(30 answers)
Closed 5 months ago.
i'm new here and still learn to become Web designer and this is my big issue
why #btnC can effect on #btnB and #btnB can't effect on #btnC ??
i try to use "~,+, , >" and all of thease didn't work i need to know more details about hovering items on each other,
could you help me please ?????
this is my code ⬇⬇⬇⬇⬇
<style>
.countainer{
width: 500px;
}
.box{
height: 100%;
}
#btnC{
display: inline-block;
text-align: center;
position: absolute;
background-color: #009fdf;
border-radius: 50px;
margin-left: 205px;
margin-top:550px;
text-decoration: none;
color:#F2F2F2;
transition: 0.8s;
}
#btnB{
display: inline-block;
text-align: center;
position: absolute;
background-color: #ffcc00;
border-radius: 50px;
margin-left: 380px;
margin-top:550px;
text-decoration: none;
color:#53565A;
transition: 0.8s;
}
#btnC div, #btnB div {
width:150px;
padding: 20px 0;
}
#btnC:hover {
transform: scale(1.2);
background-color:#ffffff;
color:#009fdf;
transition: 0.8s;
}
#btnC:hover ~ #btnB {
margin-left: 400px;
}
#btnB:hover{
transform: scale(1.2);
background-color:#ffffff;
color:#ffcc00;
transition: 0.8s;
}
#btnB:hover #btnC {
margin-left: 195px;
}
</style>
<div class="countainer">
<div class="box">
<a id="btnC" href="#"><div>Individual</div></a>
<a id="btnB" href="#"><div>Team</div></a>
<img src="https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/a8687897-418c-40db-b92b-af479b5b1cb6/d5cyk3x-ee5a53c6-240b-400a-8ee6-64e0ac9bd4ed.jpg/v1/fill/w_900,h_360,q_75,strp/background_2012_by_davicinpuntocom-d5cyk3x.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwic3ViIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsImF1ZCI6WyJ1cm46c2VydmljZTppbWFnZS5vcGVyYXRpb25zIl0sIm9iaiI6W1t7InBhdGgiOiIvZi9hODY4Nzg5Ny00MThjLTQwZGItYjkyYi1hZjQ3OWI1YjFjYjYvZDVjeWszeC1lZTVhNTNjNi0yNDBiLTQwMGEtOGVlNi02NGUwYWM5YmQ0ZWQuanBnIiwid2lkdGgiOiI8PTkwMCIsImhlaWdodCI6Ijw9MzYwIn1dXX0.jLqQ7mUnFBNhVh_NpAO5plPheYvTtzQ0JvZ_8gLr5sY" width="1700px" alt="">
</div>
</div>
CSS have not selector for previous sibling elements, but you can use :has selector for the problem:
#btnC:has( + #btnB:hover) {
margin-left: 190px;
}

Display text overlay and apply image transparency on hover

I'm trying to make an image semitransparent on hover and display text that is otherwise set to display: none. Currently if you hover over an image, it becomes semi-transparent (.single-image:hover works), but the text doesn't appear. When the text was not set to display: none, it is positioned over the image in the bottom left-hand corner. I thought that since it is over the image, the hover pseudo-class would take effect. I also tried setting the z-index of .attribution to 1 but that didn't do anything.
<div className="image-container">
<a href={image.links.html} target="_blank" rel="noopener noreferrer">
<img className="single-image" src={image.urls.regular} alt="" />
<p className="attribution">Unsplash</p>
</a>
</div>
.image-container {
display: inline-block;
position: relative;
}
/* Text */
.attribution {
display: none;
color: white;
position: absolute;
bottom: 20px;
left: 20px;
}
.attribution:hover {
display: block;
}
.single-image {
margin: 7px;
height: 350px;
width: 350px;
object-fit: cover;
}
.single-image:hover {
opacity: 0.7;
transition: 0.5s;
}
You should move the hover function to the parent div.
Change .attribution:hover to .image-container:hover .attribution and .single-image:hover to .image-container:hover .single-image.
Strangely enough, in order for this to work, you also need to add border or background-color to your parent div. (Here is why)
I added a transparent color background-color: rgba(0, 0, 0, 0);.
.image-container {
display: inline-block;
position: relative;
background-color: rgba(0, 0, 0, 0);
}
/* Text */
.attribution {
display: none;
color: white;
position: absolute;
bottom: 20px;
left: 20px;
}
.image-container:hover .attribution {
display: block;
}
.single-image {
margin: 7px;
height: 350px;
width: 350px;
object-fit: cover;
}
.image-container:hover .single-image {
opacity: 0.7;
transition: 0.5s;
}
<div class="image-container">
<a href="#" target="_blank" rel="noopener noreferrer">
<img class="single-image" src="https://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg" alt="" />
<p class="attribution">Kitten!</p>
</a>
</div>
.cont {
position: relative;
height: 150px;
width: 150px;
margin: 1em auto;
background-color: red;
}
.layer {
position: relative;
height: 150px;
width: 150px;
color: Transparent;
}
.layer:hover { color: white; }
.cont:hover { background-color: blue;}
<div class="cont">
<div class="layer">My cool Text</div>
</div>
Why did you not set the color of the font to transparent? it's easyer. see my little example (2 minutes workaround...)
Add a bit of javascript to make the text appear aswell as the image fade.
as only one element can be in hover state even if there ontop of each other.
unless you mess around with js you might be able to 'hack' a double hover state.
try;
<div className="image-container">
<a href={image.links.html} target="_blank" rel="noopener noreferrer">
<img className="single-image" src={image.urls.regular} alt="" />
<p className="attribution">Unsplash</p>
</a>
</div>
.image-container {
display: inline-block;
text-align:center;
position: relative;
z-index:1;
}
/* Text */
.attribution {
display: none;
color: white;
position: absolute;
z-index:3;
bottom: 20px;
left: 20px;
}
.single-image {
margin: 7px;
height: 350px;
width: 350px;
object-fit: cover;
z-index:2;
}
.single-image:hover {
opacity: 0.7;
transition:opacity 0.5s ease-in-out;
will-change:opacity;
}
<script>
document.addEventListener(DOMContentLoaded,(e)=>{
const img = document.getElementsByClassName('single-image')[0];
const attrib = document.getElementsByClassName('attribution')[0];
img.addEventListener('mouseover',(e)=>{
img.style.opacity = '0.7';
attrib.style.display = 'block';
});
});
</script>

Rectangle with 1 circle side

.addcircle{
width:15%;
height:30px;
position:relative;
}
.addcircle:hover{
background: #1a1aff;
color:white;
}
.addcircle:hover a{
background: #1a1aff;
color:white;
}
.addcircle:after{
position: absolute;
z-index: 1;
left: 80%;
/* top: 0%; */
width: 30px;
height: 30px;
margin-top: 0px;
border-radius: 50%;
content: "";
}
.addcircle:hover:after{background: #1a1aff;}
<div id="main">
HOOVER LINK BELOW
<div class="addcircle">
some page
</div>
<div class="addcircle" style="width:20%">
some page 2
</div>
</div>
How to do same effect like main(1st link) for responsive width??
As you can see on example, 1st hover look nice but 2nd one not rly... any clue?
Because when i check for bigger or smaller screen my circle move some where.
Not gonna do all the work for you but it looks like you're over thinking it. You're already messing with border-radius which is the key:
a {
color: white;
padding: 5px;
border-radius: 0 1rem 1rem 0 ;
background-color: blue;
}
Some Page
<br/>
<br/>
Some Page 2
Depending on the needs of your application (will all lines fit on one line on all expected viewports?), applying this style on hover could be all you need.
As you can see below, I've used right property on .addcircle:after instead of left and used a fixed value of negative half of the width which is -15px this will lead to a semi-circle effect and the right side of your links, without regarding width of the element.
.addcircle{
width:15%;
height:30px;
position:relative;
}
.addcircle:hover{
background: #1a1aff;
color:white;
}
.addcircle:hover a{
background: #1a1aff;
color:white;
}
.addcircle:after{
position: absolute;
z-index: -1;
right: -15px;
width: 30px;
height: 30px;
margin-top: 0px;
border-radius: 50%;
content: "";
}
.addcircle:hover:after{
background: #1a1aff;
}
<div id="main">
HOOVER LINK BELOW
<div class="addcircle">
some page
</div>
<div class="addcircle" style="width:20%">
some page 2
</div>
</div>
However, there's no need to use a <div class="addcircle"> around your links. It's possible to implement exact same effect with only <a> elements.
a{
width:20%;
display: block;
height: 30px;
position:relative;
}
a:hover{
background: #1a1aff;
color:white;
}
a:after{
position: absolute;
z-index: -1;
right: -15px;
width: 30px;
height: 30px;
margin-top: 0px;
border-radius: 50%;
content: "";
}
a:hover:after{
background: #1a1aff;
}
<div id="main">
<span>HOOVER LINK BELOW</span>
some page
<a style="width: 50%" href="">some page 2</a>
</div>
Just add the display property to your .addcircle div:
.addcircle{
width:15%;
height:30px;
position:relative;
display: flex;
}
and for .addcircle:after change right position instead of left:
.addcircle:after{
position: absolute;
z-index: 1;
right: -12px;
width: 30px;
height: 30px;
margin-top: 0px;
border-radius: 50%;
content: "";
}

Transition from sentence to one word

What I am trying to achieve is to animate an element width few words in the way that hovered word leaves in the center of the element and the rest smoothly goes out of the bounds. I would also keep it as clear as possible in HTML and not to use fixed pixel amount of margins/widths to position elements.
The very lousy sketch of what I have on my mind is here:
* {
transition: all 1.5s;
}
div {
min-width: 150px;
width: 30%;
height: 25px;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
}
div:hover {
background: white;
word-spacing: 300px;
}
a:hover::after,
a:hover::before {
content: ' ';
}
<div>
<a class="afirst" href="">First</a> & <a class="asecond" href="">Second</a>
</div>
Each word on hover should go to center (possibly not with those 'jumps' visible now when other words disapear). Do you have any ideas? I'm pretty sure that the way I try to follow with word-spacing is wrong.
The issue is that when increasing word spacing the text goes to new line and create this jump thing. So you may add white-space: nowrap and you can also use padding-left to push text and make it in the center :
div {
min-width: 150px;
width: 180px;
height: 25px;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
transition: all 0.5s;
box-sizing: border-box;
white-space: nowrap;
}
div:hover {
word-spacing: 80px;
padding-left: 80px;
background: white;
}
<div>
<a class="afirst" href="">First</a> & <a class="asecond" href="">Second</a>
</div>
Actually the word spacing is applied to the div so you cannot apply hover on word. It's also easier to apply this technique on the first word as the second one will be hide with overflow, but am not sure how you can do the same with the second word with the use of word-spacing.
Here is another idea on how you can do without word-spacing. I used some padding animation and also pseudo element to hide the first word when hovering the second one.
div {
min-width: 150px;
width: 180px;
height: 25px;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
transition: all 0.5s;
box-sizing: border-box;
white-space: nowrap;
}
.afirst,
.asecond {
position:relative;
display: inline-block;
transition: all 0.5s;
}
.afirst:hover {
padding: 0 44%;
background: white;
}
.asecond:hover {
padding: 0 50% 0 0;
background: white;
}
.asecond:hover::before {
content:" ";
position:absolute;
left:-50%;
width:50%;
top:0;
bottom:0;
z-index:99;
background:#fff;
}
<div>
<a class="afirst" href="">First</a> & <a class="asecond" href="">Second</a>
</div>
I think you can generalize this solution by using :before element in the left and :after element in the right to hide everything else.
Here is an example with multiple word (but not giving center alignement correctly, still need improvement) :
div {
min-width: 150px;
height: 25px;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
transition: all 0.5s;
box-sizing: border-box;
white-space: nowrap;
}
.word {
position: relative;
display: inline-block;
transition: all 0.5s;
}
.word:hover {
background: white;
padding: 0 40%;
}
.word:hover::before {
content: " ";
position: absolute;
left: -50%;
width: 50%;
top: 0;
bottom: 0;
z-index: 99;
background: #fff;
}
.word:hover::after {
content: " ";
position: absolute;
right: -50%;
width: 50%;
top: 0;
bottom: 0;
z-index: 99;
background: #fff;
}
<div>
<a class="word" href="">First</a> &
<a class="word" href="">Second</a> &
<a class="word" href="">third</a> &
<a class="word" href="">Fourth</a>
</div>
Another solution with perfect centering but less animation for the other words :
div {
position:relative;
height: 25px;
width:500px;
margin:0 auto;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
transition: all 0.5s;
box-sizing: border-box;
white-space: nowrap;
}
.word {
position: relative;
z-index:9;
display: inline-block;
transition: all 0.5s;
}
.word:hover {
position:absolute;
right:0;
left:0;
top:0;
bottom:0;
text-align:center;
background: white;
z-index:99;
}
<div>
<a class="word" href="">First</a> &
<a class="word" href="">Second</a> &
<a class="word" href="">third</a> &
<a class="word" href="">Fourth</a>
</div>
This version uses Flex Box, accommodates multiple items, and does not use fixed widths.
The trouble I kept having playing around with this was centering items without using fixed widths. Especially those that were later in line and trying to push items to the left.
Solution: flex box order.
You can set the order of flex items numerically, so simply setting it to -1 on hover puts the hovered item first in the list so you eliminate the issue of flexing items leftward.
The animation may not be as fluid as you're looking for because you can only transition order by integer. So it's immediately set along with the width, and then the other properties transition.
div.outer {
width: 50vw;
height: 30px;
background: orange;
text-align: center;
overflow: hidden;
position: relative;
padding: 0;
}
div.inner {
position: relative;
margin: 0 auto;
height: 30px;
width: 50vw;
display: flex;
justify-content: center;
align-items: center;
background: transparent;
flex-wrap: wrap;
}
span {
order: 1;
padding: 0 3px;
flex-shrink:1;
}
a {
z-index: 0;
order: 1;
height: 30px;
line-height: 30px;
flex-grow: 0;
flex-shrink: 1;
transition: background .5s, flex-grow .25s, flex-shrink .25s;
}
a:hover {
z-index: 10;
width: 50vw;
order: -1;
flex-grow: 1;
background: #eee;
}
<div class="outer">
<div class="inner">
First
<span>&</span>
Second
<span>&</span>
Third
</div>
</div>
This isn't perfect, but I think it comes pretty close to achieving what you were looking for. Using a little bit of jQuery was necessary for math (but not the animations themselves).
Hope this gets you further!
function reset() {
// reset all spans
$('.animate span').css('transform', '');
$('.animate span.active').removeClass('active');
}
$('.animate').on('mouseover', 'span:not(.active)', function() {
reset();
// set current hovered word to active
$(this).addClass('active');
// slide over previous/next words
$(this).prevAll().css('transform', 'translateX(-100vw)');
$(this).nextAll().css('transform', 'translateX(100vw)');
// determine offset for center of hovered word
var center = (window.innerWidth / 2) - ($(this).offset().left + ($(this).width() / 2));
// slide current word to center
$(this).css('transform', 'translateX(' + center + 'px)');
});
// when leaving animate section, reset
$('.animate').mouseleave(reset);
.animate {
background-color: orange;
color: white;
font-family: sans-serif;
text-align: center;
transition: .5s background-color, .5s color;
}
.animate:hover {
background-color: white;
color: orange;
}
span {
display: inline-block;
transition: 3s transform;
}
a {
color: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="animate">
<span>First</span> <span>&</span> <span>Second</span> <span>&</span> <span>Third</span> <span>and</span> <span>Fourth</span>
</div>

opacity being applied to inside div when I don't want to

I am setting a wrapper to be full screen with a slight opacity. Within that wrapper I have another div which is to be centered on the screen. All works, but the opacity is being applied to the inner div (loading icon and some text).
The html cannot change in the sense that .dataTables_processing will always be a wrapper no matter what.
html:
<div class="dataTables_processing">
<div class="dataTables_processing_custom">
<i class="fa fa-spinner fa-spin"></i> Please wait...
</div>
</div>
css:
.dataTables_processing {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
margin-left: 0;
padding: 0;
background-color: #333;
opacity: 0.05;
cursor:wait;
z-index:9998;
}
.dataTables_processing_custom {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
height: 30px;
margin-left: -100px;
text-align: center;
color:#3276b1;
font-size: 14px;
z-index:9999;
}
.dataTables_processing_custom i{
font-size:30px;
vertical-align:middle;
}
When the CSS style opacity is applied to the parent, it does it to all it's children, try using a RGBA method for a background instead:
.parent {
background: rgba(0,0,0,0.5);
}

Resources