I want to show a text animation where the second text moves in from the bottom and the first text moves out to the top. Here's the basic HTML structure:
<span style="position: relative; overflow: hidden; padding-right: 100px;">
<span style="display: block; position: absolute; left: 0px; top: 0px;">Text1</span>
<span style="display: block; position: absolute; left: 0px; top: 20px;">Text2</span>
</span>
Animation and layout details are left out for brevity.
Update: Here's a complete example for you to play with: http://jsfiddle.net/xpvt214o/577089/
My main issue is that the outside element should not be visible, but it is. The overflow property has no effect at all. How can I solve this?
The outer span element is inline because it flows in other text. Only parts of the sentence should swap out. And the animating text must be properly aligned with the rest of the sentence. inline-block for the outer element doesn't do that.
The clipping must also apply during the animation of the inner elements (transition: top 0.5s).
I've found the CSS properties clip and clip-path. The former being deprecated (and it doesn't work, too) and the latter being experimental and not supported in all required browsers (and it also fails in Firefox).
You have to use either inline-block or block in order to get the clipping to work. The thing is: if you have a blocky element that only contains absolutely positioned childs or is empty, it wont have any dimension - you have to set this manually. Try:
<span style="display: inline-block; position: relative; overflow: hidden; padding-right: 100px; height: 1.2em; line-height: 1.2em; vertical-align: bottom;">
<span style="display: block; position: absolute; left: 0px; top: 0px;">Text1</span>
<span style="display: block; position: absolute; left: 0px; top: 20px;">Text2</span>
</span>
I'm not sure why you are using inline CSS and SPANs for this but I think I've got the answer for you. Please check my solution and let me if you are not clear about it.
You can do this just using one element, using pseudo elements and nothing else. And SPAN is an inline element so you can assign inline-block to it.
Regards,
AB
.hover-text {
display: inline-block;
background-color: grey;
color: transparent;
color: white;
padding: 10px 25px;
position: relative;
overflow: hidden;
}
.hover-text:before {
content: 'Text 1';
padding: inherit;
position: absolute;
left: 0;
top: 0%;
background-color: inherit;
transition: 0.2s ease all;
}
.hover-text:after {
content: 'Text 2';
padding: inherit;
position: absolute;
left: 0;
bottom: -100%;
background-color: red;
transition: 0.2s ease all;
}
.hover-text:hover:before {
top: -100%;
}
.hover-text:hover:after {
bottom: 0%;
}
<span class="hover-text">Text 1</span>
Related
I am having trouble properly stacking my divs using CSS z-index. In my code, if I set .nose::before and .nose::after to z-index: -1, it puts the two divs at the very back of the stack. However, I just these divs to sit behind the .nose div. Here's my code:
*, *::after, *::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body { height: 100%; }
body {
background: #44BBA4;
}
.head {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 375px;
width: 400px;
background: #df9e27;
border-radius: 50%;
border: 10px solid #000;
}
.head::before, .head::after {
content: "";
position: absolute;
height: 90px;
width: 90px;
background: #df9e27;
border-radius: 50%;
border: 10px solid #000;
z-index: -1;
}
.head::before {
top: -30px;
left: 40px;
}
.head::after {
top: -30px;
right: 40px;
}
.eye {
position: absolute;
top: 150px;
height: 25px;
width: 25px;
background: #000;
border-radius: 50%;
}
.eye.left {
left: 90px;
}
.eye.right {
right: 90px;
}
.eye::before {
content: "";
position: absolute;
top: -50px;
left: -37px;
height: 100px;
width: 100px;
border-radius: 50%;
border: 12px solid transparent;
border-top: 12px solid #000;
}
.nose {
position: absolute;
margin: auto;
right: 0;
left: 0;
bottom: 130px;
height: 30px;
width: 30px;
background: #000;
border-radius: 50%;
}
.nose::before, .nose::after {
content: "";
position: absolute;
height: 68px;
width: 73px;
background: #fff;
border-radius: 50%;
border: 10px solid #000;
z-index: -1;
}
<div class="head">
<div class="eye left"></div>
<div class="eye right"></div>
<div class="nose"></div>
</div>
In short: Set z-index on your head element. Move ears out of the head element.
Here is why.
z-index has stacking contexts. Each of those contexts has a root element (just any html element). Now, to become a root element it must comply with any of the following rules:
be <html> element
position other than static and z-index other than auto
opacity less then 1
So the default stacking context is with the <html> element as a root.
Once the element is inside a scope (in other words, child of a root element), it can only be positioned relative to the elements inside the scope.
Think about it as a nested list.
Wrap here is a root element, as it has position set to relative and z-index to 1. And all of its children are now inside a stacking scope with the Wrap as a root.
So, like in a nested list, children of a particular element cannot appear before its root. For example, Child2 cannot appear before the Wrap, since it is scoped inside of it. But it can appear before the Child1.
Now, in your case the structure is as follows:
Notice that the head is not a root, because it doesn't comply with the rules for becoming one (positioned elements must also have z-index other than auto). Therefore when you assign z-index of -1 to the Nose::before and ::after you get this:
The elements have been positioned all the way behind the Head, because they are in the same stacking scope. But they appear on top of Head::before, since when elements have the same z-index, they are stacked according to the order of appearance in html.
Now, to prevent head children from appearing behind it, you must add z-index to it. This will make it a root element of new stacking scope.
But this creates another problem. Now ears are positioned on top of the head. This is not possible to solve with css alone, since they are inside a stacking scope of the head. And root always lies behind every of its children.
To solve it, you must move the ears out of the head. So, it means, you won't be able to use pseudoelements (before & after) anymore. I suggest creating ear elements outside of the head and wrapping everything in some other element (named bear?) with position relative. Wrapper is needed if you still want to position ears relative to the head.
The answer is mostly inspired by this article.
I've created a simple tooltip system for my website using a tooltip attribute and an ::after pseudoelement. Unfortunately, because the pseudoelement is positioned outside of its parent, it wants to wrap to the size of the parent element. Is there a way to prevent this without preventing wrapping altogether?
Fiddle: https://jsfiddle.net/v5zhf2nu/1/
CSS:
[tooltip]
{
position: relative;
cursor: help;
}
[tooltip]::after
{
pointer-events: none;
position: absolute;
content: attr(tooltip);
left: 100%;
top: 50%;
margin-left: 3px;
background-color: #111111;
color: white;
width: auto;
padding: 3px;
border-radius: 3px;
font-size: 12px;
font-weight: normal;
padding-left: 6px;
padding-right: 6px;
display: none;
z-index: 3;
max-width: 1000px;
}
[tooltip]:hover::after
{
display: inline-block;
}
HTML:
<span tooltip = "This is some information! Unfortunately, it seems to want to line break very early.">Mouse over me!</span>
Don't make the element relatively positioned. This way the containing block of the pseudo-element will be the viewport (or, hopefully, a wide enough element).
[data-tooltip] { position: static; } /* default value */
Don't set the left property of the pseudo-element. auto will compute to the static position, which is the end of the element because it's an ::after pseudo-element.
[data-tooltip]::after { left: auto; } /* default value */
Use some margin instead of top, e.g.
[data-tooltip]::after {
top: auto; /* default value */
margin-top: .75em;
}
The width of the pseudo-element won't be limited by the width of the element, only by the viewport (or the nearest positioned ancestor). You can reduce (but not increase) that limit by using max-width:
[data-tooltip]::after { max-width: 1000px; }
[data-tooltip] {
cursor: help;
}
[data-tooltip]::after {
pointer-events: none;
position: absolute;
content: attr(data-tooltip);
margin-top: .75em;
margin-left: 3px;
background-color: #111111;
color: white;
width: auto;
padding: 3px;
border-radius: 3px;
font-size: 12px;
font-weight: normal;
padding-left: 6px;
padding-right: 6px;
width: auto;
z-index: 3;
max-width: 1000px;
}
<span data-tooltip="This is some information! Unfortunately, it seems to want to line break very early.">Mouse over me!</span>
<br /><br /><br />
<span data-tooltip="This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. ">Mouse over me!</span>
Set right to a small enough value, at least minus the maximum width minus paddings, borders and margins:
right: -1015px;
If you don't want to do the calculations, you can use a tiny value like -100000000000px, but then you will need max-width. If you used the exact value you can remove max-width if you want
max-width: -1000px;
Finally, use one of these:
width: fit-content;
width: max-content;
Note they are not widely supported yet, so you may need vendor prefixes.
[data-tooltip] {
position: relative;
cursor: help;
}
[data-tooltip]::after {
pointer-events: none;
position: absolute;
content: attr(data-tooltip);
left: 100%;
top: 50%;
margin-left: 3px;
background-color: #111111;
color: white;
width: auto;
padding: 3px;
border-radius: 3px;
font-size: 12px;
font-weight: normal;
padding-left: 6px;
padding-right: 6px;
width: auto;
z-index: 3;
right: -100000000000px; /* Tiny value */
max-width: 1000px;
width: -moz-fit-content;
width: -webkit-fit-content;
width: fit-content;
}
<span data-tooltip="This is some information! Unfortunately, it seems to want to line break very early.">Mouse over me!</span>
<br /><br /><br />
<span data-tooltip="This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. This is some information! Unfortunately, it seems to want to line break very early. ">Mouse over me!</span>
Replace:
[tooltip]::after
{
position: absolute;
left: 100%;
}
With:
[tooltip]::after
{
position: relative;
left: 0;
}
Also, I don't think you need the max-width.
https://jsfiddle.net/v5zhf2nu/2/
Hi guys I'm trying to make a fancy style border that kind of highlights a block of text, its basically just two sharp lines that intersect (also gonna make them have a slow animated pulse thats subtlety noticeable, this is the code I have so far:
span.fancyTop::before {
position: relative;
right: -50px;
display: block;
width: 80%;
float: right;
height: 1px;
background: white;
z-index: 2;
content: "";
}
span.fancyRight::after {
position: relative;
right: -400px;
top: -20px;
display: block;
content: "";
float: right;
z-index: 2;
background: white;
height: 200px;
width: 1px;
float: right;
}
the only problem is it seems to push my content around:
I want to make it so that I can have the content fit nicely inside the lines but it seems to push it down, I also need it to be responsive for mobile. I'm trying to avoid using absolute positioning and I'd like to be able to use the classes reliably wherever and have the expected result. I'm not a front end designer by any means so any help would be fantastic. Thanks.
Absolutely positioned elements do not take up the DOM Space. So you may use this:
span.fancyTop::before {
position: absolute;
right: -50px;
display: block;
width: 80%;
float: right;
height: 1px;
background: white;
z-index: 2;
content: "";
}
span.fancyRight::after {
position: absolute;
right: -400px;
top: -20px;
display: block;
content: "";
float: right;
z-index: 2;
background: white;
height: 200px;
width: 1px;
float: right;
}
And make sure you position the parent relatively.
span.fancyRight, span.fancyTop {
position: relative;
}
If you change the positioning given to absolute, and add:
.fancyTop, .fancyRight { position: relative; }
I believe you'll get the result you're looking for. Absolutely-positioned elements are positioned relative to the container it's inside, so long as that container has a position associated with it.
If you want to get really fancy, just change .fancyTop and .fancyRight to .fancy and add the :before and :after pseudoclasses to the one class.
You may run into some other issues with the code you gave, like the span tag is an inline tag. I put together a fiddle for you as an example: https://jsfiddle.net/stgermaniac/p3d0a1ez/
I had this effect working on a Shopify site I designed about a year ago (http://originalchuck.com/), and then tonight, unbeknownst to me, the client decides to buy a new theme, turn it on and now one of my CSS tricks no longer works. If you go to the three images beneath the two blog posts, you'll see the problem. Roll over them, and the image opacity changes. That's the good news. The bad? Some text in a span is also supposed to appear in the dead center of each image, but now it no longer does. My code is the same as the previous theme, so why isn't it working anymore? Here's my CSS:
span.text-content, span.text-content-bags {
color: #ffffff;
font-size: 30px;
left: 0px;
opacity: 0;
position: absolute;
text-transform: uppercase;
top: 0px;
width: 100%;
}
span.text-content span, div.homepage-bags span.text-content-bags span {
left: 0px;
margin-top: -12px;
position: relative;
text-align: center;
top: 50%;
width: 100%;
}
.homepage-products a:hover span.text-content, .homepage-bags a:hover span.text-content-bags {
opacity: 1;
display: inline-block;
}
Here's a cool trick to center stuff inside a container:
set position: relative on the outer, containing element, and then on the element you want centered, do this:
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
display: block;
text-align: center;
You also need to set a height and width for the inner element. The units shouldn't matter.
Works in all browsers including at least IE8+. It may even go further back than that.
I have a few pictures in a table that they work as a link and in hover a play button should appear over them.
I tried many different tricks but they all have problems which dont work properly. I decieded to share my question here to find an standard solution.
Here is what I have done so far:
img{
position: relative;
}
img:hover:before {
background:url(http://i40.tinypic.com/i3s4dc.png) no-repeat center center;
content:"";
width: 100%;
min-height: 100px;
position: absolute;
left: 0;
}
I dont know if I am in the right direction or not, but have a look at the demo http://jsfiddle.net/jmXdh/8/ and if it is wrong then please let me know any other way.
You unfortunately can't use the ::before and ::after pseudo-elements with replaced elements. The content of all replaced elements is outside the scope of CSS.
From the Generated and Replaced Content Module (WD):
Replaced elements do not have '::before' and '::after' pseudo-elements; the 'content' property in the case of replaced content replaces the entire contents of the element's box.
Here's something that might work, assuming you can add additional markup:
http://jsfiddle.net/isherwood/jmXdh/11/
a {
display: inline-block;
overflow: hidden;
position: relative;
}
a:hover .play {
background:url(http://placehold.it/80x80) no-repeat center center;
opacity: 0.8;
position: absolute;
width: 80px;
height: 80px;
left: 50%;
top: 50%;
margin-left: -40px;
margin-top: -50px;
}
<a href="/">
<div class="play"></div>
<img class="img" src="http://i42.tinypic.com/2v9zuc1.jpg" />
<br />
<b>Video test</b>
</a>
Or with a transition effect:
http://jsfiddle.net/isherwood/jmXdh/12/
.play {
opacity: 0;
transition: opacity 0.3s;
}
a:hover .play {
opacity: 0.7;
}