Transition from sentence to one word - css

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>

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;
}

css transition not working correctly in vuejs

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>

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>

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);
}

How can I keep the progress bar number value centered and on top?

I have a set of progress bars displaying different values in real time. My only problem is that I can't seem to figure out how to keep the number value in the center of the bar, as well as on top at all times. Right now it's being pushed 'ahead' of the blue bar, and disappears when it goes outside the right side of the bar.
Here's how it looks:
Markup:
<td class="gridTableCell">
<div style='position: relative' class='progress progress-info'>
<div class='bar' id='signalRdepthRangePercentage-#:ViewUnitContract.ConveyanceId #' style='width: #: DepthRangePercentage#%'>
</div>
<span class='gridSpan' id='signalRdepth-#:ViewUnitContract.ConveyanceId #'>#: ViewUnitContract.CurrentRun.LatestWellLogEntry.Depth#</span>
<span class='hidden' id='signalRMaxDepthRange-#:ViewUnitContract.ConveyanceId #'>#: MaxDepthRange#</span>
<span class='hidden' id='signalRMinDepthRange-#:ViewUnitContract.ConveyanceId #'>#: MinDepthRange#</span>
</div>
</td>
And my css 'gridSpan':
.gridSpan {
position: absolute;
top: 0px;
z-index: 2;
text-align: center;
color: #676767;
width: 100%
}
The first of the three spans is the one that displays the number value inside the bar.
Any suggestions how I can keep this centered at all times, and not pushed in front of the blue filler with a huge margin?
Do something like the following:
FIDDLE
The outer element has text-align:center
The gridSpan element has display:inline-block (not absolutely positioned)
The inner element (with the blue % progress) needs to be absolutely positioned, so as not to be effected by the text-align:center.
Markup:
<div class="outer">
<span class="inner"></span>
<span class="gridSpan">9048.343</span>
</div>
CSS
.outer
{
width: 70%;
margin:20px;
height: 30px;
border: 1px solid gray;
overflow: hidden;
border-radius: 15px;
position:relative;
text-align: center;
}
.inner
{
background: aqua;
display:inline-block;
position:absolute;
left:0;
width: 20%;
height: 30px;
}
.gridSpan {
display:inline-block;
margin-top: 5px;
color: #676767;
position: relative;
z-index:2;
}
Alternatively, if you knew the width of the value you could do this by adding display:block;left:0;right:0 and margin:0 auto to your class:
.gridSpan {
display:block;
position: absolute;
margin: 0 auto;
top: 0px;
left:0;
right:0;
z-index: 2;
color: #676767;
width: x px; /*(width of value)*/
}
Actually, I finally figured this out based on this fiddle:
http://jsbin.com/apufux/2/edit (Wonder why I've never seen this post before!?)
Seems that I was missing some style overrides to the .bar and .progress part:
.progress {
position: relative;
}
.bar {
z-index: 1;
position: absolute;
}
.progress span {
position: absolute;
top: 0px;
z-index: 2;
text-align: center;
color: #676767;
width: 100%
}
Anyways, thanks for your effort! :)

Resources