Transition from a sentence to a single word

What I'm trying to achieve is to animate the width of an element to a few words so that the hovering word remains in the center of the element and the rest smoothly extends beyond the borders. I would also set it as clear as possible in HTML and not use a fixed number of field / width pixels to position elements.

The lousiest sketch of what I have in 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 the hover should go to the center (perhaps not with the β€œleaps” visible now when other words disappear). Do you have ideas? I am sure that the way I try to follow the word is wrong.

+5
source share
3 answers

The problem is that when the distance between the texts increases, the text goes to a new line and creates this transition thing. That way you can add white-space: nowrap , and you can also use padding-left to enter text and create 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 a word hover. It is also easier to apply this technique on the first word, since the second will be hiding with overflow, but I'm not sure how you can do the same with the second word using line spacing.


Here's another idea on how you can get along without markup. I used add-on animation as well as a pseudo-element to hide the first word when the second falls.

 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 using the : before element on the left and : after in the right to hide the rest.

Here is an example with a few words (but the alignment of the center is not correct, you still need to improve):

 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 excellent centering but less animation for 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> 
+2
source

This version uses the Flex Box , holds several elements , and does not use a fixed width .

The problem I kept playing with was to center the elements without using a fixed width. Especially those who were later in line and tried to pull objects to the left.

Solution : flex box order .

You can set the order of flexible elements numerically, so just set it to -1 when you hover over the first element in the list to eliminate the problem of bending the elements to the left.

The animation may not be as fluid as you are looking for, because you can only translate the order by an integer. Therefore, it is immediately set with the width, and then goes on to other properties.

 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"> <a href="">First</a> <span>&amp;</span> <a href="">Second</a> <span>&amp;</span> <a href="">Third</a> </div> </div> 
+1
source

This is not perfect, but I think it is approaching what you were looking for. Using a bit of jQuery was necessary for the math (but not for the animations themselves).

Hope this is even more!

 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><a href="#">First</a></span> <span>&amp;</span> <span><a href="#">Second</a></span> <span>&amp;</span> <span><a href="#">Third</a></span> <span>and</span> <span><a href="#">Fourth</a></span> </div> 
0
source

Source: https://habr.com/ru/post/1273481/


All Articles