I'm creating a tooltip. My problem is that when the tooltip appears, the siblings move, unlike position: absolute. I can't use an absolute position because that positions the tooltip relative to the browser window, and not it's original position.
HTML
<p class="tooltip-anchor">Hover me</p>
<span class="tooltip">Hello!</span>
CSS
.tooltip-anchor:hover + .tooltip {
display: inline-block;
}
.tooltip {
display: none;
position: relative;
color: #fff;
background: #333;
padding: 0.25em;
}
I made a demo on Code Pen.
Whit some modes to your code you can obtaine what do you want.
If you insert your span into the p tag you can set a position:absolute to the span (and position relative to it's container) and then modify it's position as you want.
Position absolute: The element is removed from the normal document
flow, and no space is created for the element in the page layout. It
is positioned relative to its closest positioned ancestor, if any;
otherwise, it is placed relative to the initial containing block. Its
final position is determined by the values of top, right, bottom, and
left.
body {
font-family: sans-serif;
font-size: 18px;
text-align: center;
}
.tooltip-anchor {
position: relative;
display: inline-block;
}
/* modified */
.tooltip-anchor:hover .tooltip {
display: inline-block;
}
.tooltip {
display: none;
position: absolute;
bottom: 20px;
/* modified */
left: -40px;
/* modify for center */
color: #fff;
background: #333;
padding: 0.25em;
min-width: 150px;
text-align: center;
}
<p style="font-size: 17px;">A simple tooltip. CSS is wonderful, may I say.</p>
<p class="tooltip-anchor">Hover me <span class="tooltip">Hello!</span></p>
<p>Hello</p>
Related
I have this buttons which have a hover effect that renders a span on top of the hovered button.
It works fine, but, when the width of the screen changes, it looks very bad:
These are the elements:
<div className='buttons'>
<button
className={editor.isActive('bold') ? 'is-active' : 'is-inactive'}
>
<strong>N</strong>
<span className='popup'>Negrita (Ctrl+B)</span>
</button>
<button
className={editor.isActive('italic') ? 'is-active' : 'is-inactive'}
>
<em>C</em>
<span className='popup'>Cursiva (Ctrl+I)</span>
</button>
<button
className={editor.isActive('strike') ? 'is-active' : 'is-inactive'}
>
<s>T</s>
<span className='popup'>Tachado (Ctrl+Shift+X)</span>
</button>
... (you get the idea)
</div>
This is the scss:
.buttons button {
position: relative;
height: 29.19px;
color: #000;
border: 1px solid black;
border-radius: 0.3rem;
margin: 0.2rem !important;
padding: 0.1rem 0.4rem !important;
background: white;
accent-color: black;
font-weight: 500;
}
button .popup {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
bottom: 100%;
left: 50%;
margin-bottom: 5px;
margin-left: -60px;
}
button .popup::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: black transparent transparent transparent;
}
button:hover .popup {
visibility: visible;
}
What im looking for
I decided that the best solution would be a horizontal scroll. The problem is that the span is absolute positioned based on the button so i cant figure it out a way to keep the span on top of the hovered button while having an horizontal scroll.
Update 1
Ok, i tried to add a scroll, this is whats happening now:
As you can see, the scroll is working fine but the spans are 'covered', is there a way to fix this?
I added this to the code:
.buttons {
position: relative;
overflow-x: scroll;
white-space: nowrap;
}
Have a look at the definition of the absolute here
The element is removed from the normal document flow, and no space is
created for the element in the page layout. It is positioned relative
to its closest positioned ancestor, if any; otherwise, it is placed
relative to the initial containing block.
And positioned ancestor:
A positioned element is an element whose computed position value is
either relative, absolute, fixed, or sticky. (In other words, it's
anything except static.)
So, it should work even while having an horizontal scroll if you set position:relative for .buttons.
This question already has answers here:
Thick underline behind text
(7 answers)
Closed 8 months ago.
I am trying to use a background color on text only, which works fine on single lines, but when the line breaks in responsive mode it ends up looking like this:
Does anyone know what to add to make the yellow background line follow the text on mulitple lines?
This is my code:
.background-highlight {
position: relative;
display: inline-block;
color: #faf9f4;
}
.background-highlight:after {
content: '';
position: absolute;
width: 100%;
height: 10px;
left: 0;
top: 50%;
background-color: #cef230;
z-index: -1;
}
Thanks a lot in advance,
I have used box-decoration-break: clone; property for mainting the same design for multiple lines don't forget to add display: inline; to its child where background is added. in child I have used linear gradient you can generate according to you from here. you can chenge the position of green strip by adjusting gradient values from the site.
.background-highlight {
position: relative;
display: inline-block;
color: #000;
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
font-size: 120px;
}
.background-highlight span {
display: inline;
background: rgb(206,242,48);
background: -webkit-gradient(linear, left bottom, left top, color-stop(11%, rgba(206,242,48,1)), color-stop(12%, rgba(255,255,255,0)));
background: -o-linear-gradient(bottom, rgba(206,242,48,1) 11%, rgba(255,255,255,0) 12%);
background: linear-gradient(0deg, rgba(206,242,48,1) 11%, rgba(255,255,255,0) 12%);
}
<h1 class="background-highlight"><span>The skippers escape</span></h1>
It is fault of pseudo element that is forced to break between two lines.
The cause is the way the effect is carried out, pseudo element ::before creates a single rectangle that has no way of splitting up to follow words flow. Posible solutions:
Make sure links never occupy more than 1 line. You can use
white-space: nowrap;
Redesign the effect applying box border to main element. For example:
.background-highlight {
width: max-content;
border-bottom:5px solid rgb(217, 255, 0);
}
<div class="background-highlight">THE SKIPPER´S ESCAPE</div>
Pseudo-element solution
Use the bottom-positioning value on the pseudo-element instead of top. This forces the pseudo-element to be positioned at the bottom, instead of 50%from the top. I used bottom: -10px as that is the height of the pseudo-element, so it aligns perfectly.
Read more on position values: https://developer.mozilla.org/en-US/docs/Web/CSS/position
HTML-element solution
Instead of creating a pseudo-element, you could opt to make an HTML element instead.
Make a parent container, apply flex to it so the text and the line will align.
Make the .line-element a block element, so it will break into a new line.
You can still apply position: absolute and position: relative on the .line and the h2 if you want to position it in another way. Or you could simply use e.g. transform: translateY(5px) to move the line up a bit.
.background-highlight {
position: relative;
display: inline-block;
color: black;
text-align: right;
}
.background-highlight:after {
content: '';
position: absolute;
width: 100%;
height: 10px;
left: 0;
bottom: -10px;
background-color: #cef230;
z-index: -1;
}
/* Without pseudo */
.nopseudo {
display: flex;
}
.nopseudo h2 {
text-align: right;
}
.nopseudo .line {
height: 10px;
width: 100%;
background-color: #cef230;
display: block;
}
<h2 class="background-highlight">The Skippers <br>Escape</h2>
<div class="nopseudo">
<h2>The Skippers <br>Escape<span class="line"></span></h2>
</div>
I don't know how is your structure but this might help.
We just need two div elements, one as a container to setup the width property and the text holder in this case I will use a h2 tag.
Just mkae the ::after pseudo element as display and the .background-highlight's width can be width: match-content or 100% in this case if you just want to cover the text use match-content if you want to cover the width of the .title element use 100%
.title {
width: 90vw;
text-align: end;
}
h2 {
text-transform: uppercase;
color: #374650;
}
.fullwidth {
width: 100%;
}
.match {
width: match-content;
}
.background-highlight {
position: relative;
display: inline-block;
}
.background-highlight:after {
content: '';
display: block;
width: 100%;
height: 10px;
background-color: #cef230;
z-index: -1;
}
<div class="title">
<h2 class="match background-highlight">
The Skipper's <br>Escape</h2>
</div>
<div class="title">
<h2 class="fullwidth background-highlight">
The Skipper's <br>Escape</h2>
</div>
This question already has answers here:
How do I debug CSS calc() value?
(2 answers)
Closed 10 months ago.
I have a div element that I want to put a button in, and I want to use the calc() function to move the button down relative to the position of that div element, but it returns as an "Invalid property value" according to chrome dev tools.
#rArrow {
top: calc(inherit + 80px);
height: 76px;
padding: 8px;
position: absolute;
text-align: center;
width: 28px;
}
calc() is suppose to calculate using a mathematical expression like -, +, * or /. According to your problem the inherit keyword can only exist alone as a value in a property declaration. It cannot be used with functions like calc() either.
The Real Problem
It's already been mentioned from previous answers (fadzrinmadu and Samitha Wijesekara) why inherit isn't a valid value for calc(). I will address your actual problem that lead you to try to adjust the top property in the first place. I'm assuming that the distance between the top of the <button> and the top of the containing <div> (<menu> in example) was not 80px.
The Explanation
A tag that has position: absolute measures all of it's positions (top, bottom, right, and left) in relation to it's nearest ancestor tag that has position: relative. If there's no ancestor tag with position: relative, then the distance is set between the edge of the page and the edge of the tag with position: absolute.
The Solution
Add position: relative to the containing <div>
In the example below there are two <menu> tags, each with a button.
The <menu> on the left has position: relative
The <menu> on the right has position: static (that's default and it's the same as not having position at all).
/* ✳️ Most Relevant */
/* For Demo Only */
main {
display: flex;
justify-content: center;
align-items: center;
}
menu {
position: relative; /* ✳️ */
width: 84px;
height: 236px;
border: 1px dashed tomato;
}
/* For Demo Only */
.static {
position: static;
}
.rArrow {
position: absolute; /* ✳️ */
top: 80px; /* ✳️ */
width: 28px;
height: 76px;
padding: 8px;
font-size: 3rem;
text-align: center;
}
/* Optional */
.rArrow::before {
content: '▶';
display: block;
margin: 2.5px 0 0 -9px;
color: magenta;
transform: scaleY(2) scaleX(0.5);
}
/* For Demo Only */
b {
display: block;
width: 12px;
height: 80px;
font-size: 3rem;
text-align: center;
}
/* For Demo Only */
b::before {
content: '⇕80px';
display: block;
margin: 10px 0 0 0;
font-family: Consolas;
color: #930;
transform: scaleY(2) scaleX(0.5);
}
/* For Demo Only */
.offset {
margin-top: -24px
}
<main>
<menu>
<b><!--For Demo Only--></b>
<button class='rArrow'></button>
</menu>
<menu class='static'>
<b class='offset'>
<!--For Demo Only-->
</b>
<button class='rArrow'></button>
</menu>
</main>
When you use "initial" value top/left/right/bottom it means the value becomes "auto". the calc() function in css only accepts values "length", "frequency", "angle", "time", "percentage", "number", or "integer" is allowed.
ref : CSS Calc()
I'm trying to achieve a sliding-door effect on a span contained within an h2 element. The h2 element has position set to relative in order to enable z-index, so far so good.
The span is floated to the right within this h2 element and has a z-index set to lower than the h2's in order to slide under it when the view contracts, but keep sticking out under as if only the 'float' matters here.
But here's what I get instead, followed by what I wish to get:
Current result of z-indexed span within z-indexed h2:
Desired result
CSS for containing H2 element:
width: 400px;
height: 24px;
font-size: 13px;
vertical-align: bottom;
position: relative;
z-index: 5;
padding: 2px;
color: white;
text-align: left;
background: url('left-door.gif') top left no-repeat;
CSS for nested span element:
width: 200px;
height: 100%;
float: right;
z-index: 0;
text-align: center;
background: url('right-door.gif') top right no-repeat;
Anyone knows why the span refuses to sit level with the h2 even though the h2's fixed height ought to cap it within (setting clear: both on the h2 did nothing), and to be obscured by it when the view shrinks? It is because it's nested?
(Also, 'vertical-align' has no effect, the text doesn't settle on text-bottom but sits in vertical middle. Btw, just got started with this tinkering, but happen to be in a hurry. thanks.)
Edit: After BHouwens answer, i tried by reducing the text content of the H2 (real code has text), and the span aligns level, only problem is the z-index doesn't seem to work, but from what I remember from a previous question, z-index doesn't work on nested elements, as in they can't be stacked above or below their parent. Thanks for helping to troubleshoot! This has helped me focus better, and now think I'll just add two spans within the h2!
May be, below code will work for you!
h2 {
width: 400px;
height: 24px;
font-size: 13px;
vertical-align: bottom;
position: relative;
display: table-cell;
z-index: 5;
padding: 2px;
color: white;
background: #ff0;
}
span {
width: 200px;
height: 100%;
right: 0px;
top: 0px;
z-index: 0;
text-align: center;
background: #f00;
position: absolute;
}
span .wrap {
display: table-cell;
height: 24px;
width: inherit;
vertical-align: bottom;
text-align: center;
}
<h2>
H2
<span>
<div class="wrap">Span</div>
</span>
</h2>
Made a fiddle with your code only, which achieves your desired result: https://jsfiddle.net/dzpfkoLy/
My guess is you've got some other CSS acting on these elements (you can inspect with dev tools in Chrome or Firefox to see what this could be). Otherwise, if you want to ensure the result you need, you can set your span to
span {
// other span styling
position: absolute;
right: 0;
top: 0;
}
Which will shunt it to the top right of the h2. You can then play with z-index to get whatever kind of ordering you're after.
I know it is possible to create a custom "tooltip" with the :hover:after selectors and to align this tooltip relative to the original element by marking the original element as position:relative and the tooltip as absolute.
HTML:
test
<span custom-tooltip="testing a custom tooltip" class="tooltip">
test
</span>
test
CSS:
.tooltip {
position: relative;
}
.tooltip:hover:after {
content: attr(custom-tooltip);
position: absolute;
background: black;
color: white;
}
However, I must use absolute values to position or size this :after element
top: 30px;
left: -30px;
width: 300px;
What if I want to make the element as wide as it needs to be (Percentages are relative to the parent element creating a large vertical box so I can't tell it to go width: 100%)
And centered under the parent (left: -50% results in it being moved 50% of the parent to the left, not centered)
Is this possible without javascript? (If not, are there some magic selectors or functions to get the width of this or that and calc() the correct values?
You can force the tooltip onto a single line by using white-space:nowrap. I don't know of any way to center the tooltip without forcing a specific width on both the tooltip and the item the tooltip applies to. Here's a general-purpose example (without centering):
<p>Lorem <span tooltip="Lorem ipsum">ipsum</span> dolor sit amet.</p>
And the CSS:
*[tooltip] {
position: relative;
border-bottom: dotted 1px #000;
}
*[tooltip]:hover:before {
content: attr(tooltip);
background-color: #000;
color: #fff;
top: 1em;
position: absolute;
white-space: nowrap;
}
Note that I'm using :before instead of :after. If you want to center the tooltip and are able to define a fixed width, you can use this CSS instead:
*[tooltip] {
position: relative;
display: inline-block;
text-align: center;
width: 200px;
margin: 0 -75px;
}
*[tooltip]:hover:before {
content: attr(tooltip);
background-color: #000;
color: #fff;
top: 1em;
position: absolute;
white-space: nowrap;
width: 200px;
}
Here, the item is given a fixed width equal to the width of the tooltip then negative left/right margins to collapse it back down to the desired size. Note the addition of display:inline-block and text-align:center.
This technique isn't practical for inline tooltips, but works well for buttons and "call to action" links.
.tooltip
{
display: inline;
position: relative;
}
.tooltip:hover:after
{
background: #333;
background: rgba(0,0,0,.8);
border-radius: 5px;
bottom: 26px;
color: #fff;
content: attr(title);
left: 20%;
padding: 5px 15px;
position: absolute;
z-index: 98;
width: 220px;
}
code from TalkersCode complete code here Create CSS3 Tooltip