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/
Related
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>
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 have a simple div wrapper with four spans inside.
<body>
<main>
<div>
<span>One</span>
<span>Two</span>
<span>Three</span>
<span>Four</span>
</div>
</main>
</body>
The div is positioned absolutely so that I can get it to touch the bottom of the screen, and text-align is justify so the spans inside are evenly spaced. This works fine until I try to make my spans height: 100%, then a mysterious white space appears outside of the actual flow on the very bottom. I think this has something to do with my div:after psudo-element but I have absolutely no idea what's going on.
* {
padding: 0;
margin: 0;
}
main {
position: relative;
height: 100vh;
width: 100%;
background-color: rgb(45, 45, 65);
text-align: center;
}
div {
position: absolute;
top: 50%;
left: 25%;
right: 25%;
bottom: 0;
text-align: justify;
display: block;
}
div:after {
display: inline-block;
width: 100%;
content: '';
}
span {
background-color: rgb(25, 25, 45);
box-sizing: border-box;
display: inline-block;
font-size: 1em;
padding: 10px;
height: 100%;
}
span:hover {
background-color: white;
}
Do I not understand how :after works, or is this some kind of a glitch? Where in the world is that white spacing coming from on the bottom?
Here's a reproduction of the problem: http://codepen.io/anon/pen/qdpERR?editors=110
simply add an overflow: hidden; to the main or even the parent of the main should works.
Check the link
http://codepen.io/TibicenasDesign/pen/yNpyLr?editors=110
Uncomment overflow: hidden; or box-sizing: border-box then, the white space at the end of the web will be removed.
Also the box-sizing works ! i always have it with border-box so forgot it haha, and maybe its a better solution
Another option may be to add box-sizing:border-box, becauase you have padding on those link elements.
In my application I have a section header with a caption and a horizontal line. The horizontal line is a background image (which contains the line, the rest of the image is transparent) of the parent container. The caption is defined by a child element.
<div class="header">
<span>Identifier</span>
</div>
What I am trying to achieve - with CSS styling - is that the child element is displayed with the same background color as the parent, but the background image of the parent container should not be displayed underneath the caption.
.header {
background-image: url("bg_image.png");
background-color: #fff;
position: relative;
height: 25px;
}
.header > span {
position: absolute;
background-color: #fff;
padding: 0px 10px;
}
This works perfectly if I set the background color of the child element explicitly. But the background color can be configured by the user, so I don't want to set it explicitly.
So my the question is, is this possible at all using only CSS styling?
This fiddle shows the problem (I used a gradient to simulate the background image).
EDIT: An important requirement is that the solution must work across browsers (including IE8).
If you're okay with a centered headline, try the css that i used in one of my projects:
h1 {
position: relative;
white-space: nowrap;
text-align: center;
padding: .2em 0;
}
h1:before,
h1:after {
content: "";
position: relative;
display: inline-block;
width: 50%;
height: 2px;
vertical-align: middle;
background: #000;
}
h1:before {
left: -.5em;
margin: 0 0 0 -50%;
}
h1:after {
left: .5em;
margin: 0 -50% 0 0;
}
You can see the result here: http://codepen.io/DerZyklop/pen/AouDn
It is pure CSS. It adds two lines by using the css-pseudo-elements :before and :after.
With some modifications it should also work well with a left-aligned headline like in your example.
And another important thing to note here is the white-space: nowrap;. So this will only work with one line, but not with multiple lines.
can you please checkout
http://jsfiddle.net/dYr29/3/
i have update your fiddle
<div class="header">
<span>Identifier</span>
</div>
css
.header {
background: linear-gradient(to bottom, #4c4c4c 0%,#595959 12%,#666666 25%,#474747 39%,#2c2c2c 50%,#000000 51%,#111111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);
background-color: #fff;
position: relative;
width: 300px;
height: 1px;
top: 10px;
}
.header > span {
position: absolute;
padding: 0px 10px;
top: -10px;
left: 10px;
background:#fff;
}
I finally identified how to solve the problem.
.header > span {
position: absolute;
background-color: inherit;
padding: 0px 10px;
}
Using background-color: inherit will solve the problem.
I also updated the fiddle.
Click here for visual
As you can see from the picture, my parent container is not expanding to fit my child container. The page container (#contain) actually stops at the bottom left hand corner of the kitchen photograph. The child container (#zone2) is clearly overflowing outside its parent container (#contain). I would like to be able to have (#contain) expand automatically to fit (#zone2). The CSS is:
#contain {
position: relative;
width: 100%;
margin: 0 px;
background: #E3DCCC;
z-index: 0;
}
#zone1 {
width: 100%;
height: 850px;
background: url(http://waly1039.com/sites/default/files/k4.jpg) no-repeat center top;
position: absolute;
z-index: -1;
}
#head {
position: absolute;
top: 20px;
width: 100%;
height: 330px;
}
#head img {
max-width: auto;
height: auto;
}
#zone2 {
position: relative;
overflow: hidden;
padding: 3px;
top: 360px;
float: right;
right: 15px;
width: 53%;
height: auto;
border: 4px solid #715E40;
background-color: white;
}
#zone2 img {
max-width:100%;
height: auto;
float:left;
margin: 5px;
}
#zone3 {
position: relative;
top: 710px;
left: 15px;
float: left;
height: 340px;
width: 38%;
border: 4px solid #715E40;
background-color: white;
}
This is a float issue. Try adding the traditional CSS clear fix to #zone2's container:
.container:after{
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
Be sure to put this in the :after pseudo selector, otherwise it won't work for you. Floated elements exist outside of normal document flow, which is why the container isn't expanding to contain them. The clear fix forces the floats to be cleared, which will cause the container to expand around the bottom of this element.
I tested adding more images to #zone2 and #contain expands vertically. Somehow you've got an element(s) in #zone2 with padding or margins that aren't being added to the parent's total height.
If you want a quick fix in order to move on then add margin-bottom: 30px; to #zone2.
I've duplicated your problem and was able to resolve it with this: You might want to try it. It's looks a bit odd so make a class for it if you like. I'm more concern with where it is placed.
Just beneath lines of your code, add my third line. Just that and you are done. Note, it more about positioning.
<div id="zone3"></div>
<div id="zoneclear"></div>
<br style="clear:both; float:none; display:block; height:1px;" />
Just add the third line.
and just modify one of your styles:
#zoneclear {
clear: both;
float:none;
display:block;
height: 30px;
position: relative;
}
[EDIT]
The codes have a serious bug in firefox which is not present in Google Chrome (that I tested in earlier due to your relative positioning. So I've modified the #zoneclear style to fix that. You might have to test if the other browsers like this hack.
I hope it helps you