li:after auto size & :after on a :after element? - css

I have some CSS questions.
I have a li element with a certain width. I also want a :after
element for this li and use this as a tooltip. Is it possible to
give the tooltip an auto width and center it above the li?
If I have the tooltip in the li:after element working I still need a
little triangle arrow for it therefor I would need to apply a :after
element on a :after element. Is this possible?

If the order is triangle, followed by tooltip text, you can achieve this by using :before and :after (as suggested in the comment). The below example, also available on dabblet, should give you an idea.
http://dabblet.com/gist/4280779
HTML:
<ul>
<li>first - no tooltip</li>
<li data-tooltip="Tooltip second">Second</li>
<li data-tooltip="Tooltip third">third</li>
</li>
CSS:
li {
color: #900;
}
li:hover {
color: red;
position: relative;
}
li[data-tooltip]:hover:after {
content: attr(data-tooltip);
padding: 4px 6px 4px 20px;
color: yellow;
position: absolute;
left: 0;
top: -150%;
white-space: nowrap;
z-index: 20;
border-radius: 5px;
box-shadow: 0px 0px 2px #333;
background-color: black;
}
li[data-tooltip]:hover:before {
content: "\0394";
padding-left: 3px;
position: absolute;
left: 0px;
top: -150%;
color: yellow;
z-index: 21;
}
You can make the tooltip look nice by replacing background-color with background-image / gradient, etc.

Related

How to make pseudo-element follow text across line break?

I've created CSS for anchor text that transitions a background-color and a border-bottom using opacity. (This is done to meet the Chrome Lighthouse auditor's spec on avoiding transitions except on compositor-only effects.)
The CSS puts the transitioned items on a ::before pseudo-element built on the anchor. Notice that the pseudo-element is absolutely positioned, which is a requirement of the technique as currently constructed. It works except when the anchor text follows a line break. A working, illustrated example is provided on this CodePen.
The CSS and HTML are also provided here:
* {
margin: 0;
padding: 0;
}
body {
margin: 1em;
font-size: 24px;
line-height: 1.5;
}
header,
article {
display: inline-block;
margin: 1em;
width: 100%;
}
p {
padding-bottom: 1em;
}
ul {
list-style: none;
}
li {
float: left;
margin-right: 1em;
}
a {
background-color: transparent;
border-bottom-color: transparent;
border-bottom-style: solid;
color: blue;
text-decoration: none;
position: relative;
}
a::before {
background-color: lightgray;
border-bottom-color: blue;
border-bottom-style: solid;
content: '';
opacity: 0;
transition: opacity 500ms ease;
position: absolute;
top: -5px;
left: 0;
bottom: -5px;
right: 0;
z-index: -1;
}
a:hover::before {
opacity: 1;
}
a::after {
--icon-width: 24px;
color: blue;
content: '';
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImJsdWUiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWV4dGVybmFsLWxpbmsiPjxwYXRoIGQ9Ik0xOCAxM3Y2YTIgMiAwIDAgMS0yIDJINWEyIDIgMCAwIDEtMi0yVjhhMiAyIDAgMCAxIDItMmg2Ij48L3BhdGg+PHBvbHlsaW5lIHBvaW50cz0iMTUgMyAyMSAzIDIxIDkiPjwvcG9seWxpbmU+PGxpbmUgeDE9IjEwIiB5MT0iMTQiIHgyPSIyMSIgeTI9IjMiPjwvbGluZT48L3N2Zz4=);
margin-left: 0.2em;
padding-left: var(--icon-width);
background-size: var(--icon-width) var(--icon-width);
background-position: center center;
background-repeat: no-repeat;
z-index: 999;
}
<body>
<header>
<ul>
<li><a href=#>Anchor 1</a></li>
<li><a href=#>Anchor 2</a></li>
<li><a href=#>Anchor 3</a></li>
</ul>
</header>
<article>
<h1>Composited transitions on border-bottom and background-color</h1>
<p>Avoid non-composited transitions! <code>opacity</code> and <code>transform</code> transitions are preferred by the Lighthouse auditor.</p>
<p>See: Stick to Compositor-Only Properties and Manage Layer Count by
Paul Lewis of Google.</p>
<p>Hover over the links to see the <code>border-bottom</code> and <code>background-color</code> fade in to cover the link text fully. This method works so long as the anchor text does not wrap across lines.</p>
<p><strong><em>Resize the window until the long link text on the line above this one wraps to a second line. At that point, the technique fails.</em></strong></p>
<p>Can you see a solution for the CSS?</p>
</article>
</body>
How would I edit the CSS so that the ::before element follows the line break of the anchor text?

CSS tooltip background color hidden

Here's my code:
/* Tooltip container */
.tip {
position: relative;
display: inline-block;
cursor: help;/*change the cursor symbol to a question mark on mouse over*/
color: inherit;/*inherit text color*/
text-decoration: none;/*remove underline*/
}
/*Tooltip text*/
.tip span {
visibility: hidden;
width: 80%;
text-align: left;
padding: .6em;
padding-left: 1em;
border: 1px solid ;
border-radius: 0.5em;
font: 400 12px Arial;
color: #ffffff;
background-color: #000000;
display: inline-block;/*Position the tooltip text*/
position: absolute;/*positioned relative to the tooltip container*/
bottom: -5px;
top: 105%;
z-index: 100;
}
.tip:hover span {
visibility: visible;
}
<a href="javascript:void(0)" class="tip">
Container text
<span>
Tooltip text
</span></a>
I am trying to make my tooltip show up when you hover over the text. The problem is, while the text (currently in white) shows up over other elements, the background (currently in black) does not. How do I make sure that the background color shows through so that my text is visible?
The problem lies in your CSS for positioning the tooltip:
position: absolute;/*positioned relative to the tooltip container*/
bottom: -5px;
top: 105%;
You only need to specify the offset relative to the tooltip container with one attribute - either bottom or top, but not both. By using both, you're essentially defining a height for your tooltip and, since your text is too big to fit into that constrained height, it looks cut off. So just remove either top OR bottom and problem solved.
I made few changes to your css in order to make the text visible. Rest of your code looks fine. Run and check from the below Snippet.
/* Tooltip container */
.tip{
position: relative;
display: inline-block;
cursor: help; /*change the cursor symbol to a question mark on mouse over*/
color: inherit; /*inherit text color*/
text-decoration: none; /*remove underline*/
}
/*Tooltip text*/
.tip span {
visibility: hidden;
width:80%;
text-align: center;
padding: 1em 0em 1em 0em;
border: 1px solid [template("base font color")];
border-radius: 0.5em;
font: 400 12px Arial;
color: #ffffff;
background-color: #000000;
display: inline-block;
/*Position the tooltip text*/
position: absolute; /*positioned relative to the tooltip container*/
top: 105%;
z-index:100;
}
.tip:hover span {
visibility: visible;
}
<a href="javascript:void(0)" class="tip">
Container text
<span>
Tooltip text
</span></a>

Is there a LI equivalent for box-sizing: border-box?

I have a nav bar that consists of an UL with several LI items. The active nav button has a different background color, but I also need a small bottom border on the button.
When applying a border, this appears outside of the LI. When working with divs, you can use box-sizing:border-box to get the borders inside the div. But how can you offset the border on a LI item ??? (list-style-position seems to have no effect)
My scss code:
nav {
ul {
li {
float: left;
padding: 0;
box-sizing: border-box;
list-style-position: inside;
&.active {
background-color: white;
border-bottom: solid 6px blue;
box-sizing: border-box;
list-style-position: inside;
}
}
}
}
When working with divs, you can use box-sizing:border-box to get the
borders inside the div.
To clarify, box-sizing:border-box does not make the border to be within the element (change offset), it make the border size be included in the width or height, when set, so i.e. if you give li a height of 25px and bottom border 5px, the inner height will decrease to 20px.
But how can you offset the border on a LI item
You can't offset the border, one workaround to show/hide a border on an element is to use a pseudo element, which will avoid having the element jump/resize when toggle the border, but there are more ways, such as linear-gradient (shown in below sample when hover)
body {
background: lightgray;
}
nav ul li {
position: relative;
float: left;
padding: 0 5px;
list-style-type: none;
}
nav ul li.active::before {
content: '';
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: -6px;
background-color: white;
border-bottom: solid 6px blue;
z-index: -1;
}
/* or one can use linear-gradient */
nav ul li:hover {
background: linear-gradient(
to bottom, white calc(100% - 5px), blue 5px
) no-repeat left bottom;
}
<nav>
<ul>
<li>
Some text
</li>
<li>
Some text
</li>
<li class="active">
Some text
</li>
<li>
Some text
</li>
</ul>
</nav>
Updated
There is actually a way to offset the border, using border-image-outset, shown in this answer:
border-image-outset in CSS
Another fast and clean way to create an inside border is to create an inset shadow without a blur. You don't even need box-sizing or list-style.
nav {
ul {
li {
float: left;
padding: 0;
&.active {
background-color: white;
box-shadow: 0px -6px 0px red inset;
}
}
}
}

showing a span on hovering of a link using css

i have an link, when I hover it, I want a span to appear using CSS only.
HTML is here:
Rules
<span class="tooltip">
some personal information rules some personal information rules some personal information rules some personal information rules some personal information rules
</span>
CSS is here:
.tooltip{ display: none;}
.tooltip-trigger {
background: url(../images/right-arro.png) right 13px no-repeat;
background-color: #EEEEEE;
display: block;
float: left;
height: 33px;
line-height: 33px;
padding: 0 15px 0 6px;
color: #2578E8;
}
.tooltip-trigger :hover > .tooltip{ display: block;}
fiddle is here: http://jsfiddle.net/LBE55/
Two problems:
Firstly, > is the child combinator selector, not a sibling selector. Your span element isn't a child of your a element; it's a sibling. You'll want to use the adjacent sibling combinator (+) instead.
Secondly, :hover needs to be directly after .tooltip-trigger (remove the space), otherwise you're calling the hover on an element contained within your a element (of which there are none):
.tooltip-trigger:hover + .tooltip { display: block; }
JSFiddle demo.
You have to include the span inside link tag
Rules<span class="tooltip">some personal information rules some personal information rules some personal information rules some personal information rules some personal information rules </span>
The way you wrote the css, span has to be inside of a to appear
Try this I found on a tutorial:
.tooltip {
display: inline;
position: relative;
}
.tooltip:hover:after {
background: none repeat scroll 0 0 rgba(0, 0, 0, 0.8);
border-radius: 5px;
bottom: 26px;
color: #FFFFFF;
content: attr(title);
left: 20%;
padding: 5px 15px;
position: absolute;
width: 220px;
z-index: 98;
}
.tooltip:hover:before {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
border-color: #333333 rgba(0, 0, 0, 0);
border-image: none;
border-style: solid;
border-width: 6px 6px 0;
bottom: 20px;
content: "";
left: 50%;
position: absolute;
z-index: 99;
}
And the html:
<a class="tooltip" title="This is a tooltip" href="#"><span title="More">Tooltip Example</span></a>
// another way
.tooltip-trigger:hover ~ .tooltip { display: block; }

Is Firefox adding some invisible padding or margin to my absolutely positioned :after triangle?

I'm a little frustrated with the positioning of a CSS triangle on the :after pseudo-element which appears correctly in Chrome and Safari but appears to have a little extra padding or margin in Firefox.
First, screenshots:
The top screen is how "Choose a Subject" appears in Firefox, the bottom how it appears in Chrome and Safari. Obviously this is purely cosmetic, but I'm going for that chevron look.
Here is the markup (for the first item, the darker-blue item is another li):
<nav class="menu pill-menu inline" role="navigation">
<!-- Major Category
======================
--> <ul>
<li class="has-subnav primary">
<input type="checkbox" id="primary-menu" class="checkbox-toggle"/>
<label class="label" for="primary-menu">
Choose a Subject
</label>
</li>
</ul>
</nav>
Here is the Sass:
.pill-menu {
& > ul > li { display: inline-block; }
.primary > .label,
.secondary > .label {
#include css-transition(all, .2s, ease-out);
cursor: pointer;
padding: .5em;
position: relative;
}
.primary > .label {
border-radius: 5px 0 0 5px;
}
.primary > .label:after {
border-top: 18px solid transparent;
border-bottom: 18px solid transparent;
border-left: 18px solid $light-blue-object; // TODO: Abstract This
content: "";
height: 0;
right: -1em;
top: 0;
position: absolute;
width: 0;
z-index: 1;
}
}
I've tried several different things: using an :after pseudo-element, I used as I am now right: -1em; I've also scrapped than and tried left: 100%; I set the triangle to a :before element and tried an assortment there. I'm stumped.
I tried changing up the fonts, hardcoding the font-size in pixels, mucking with the padding and the margin: nothing I can think of has any effect on that little space.
I appreciate your thoughts.
In case it matters, I am using normalize.css.
Additionally, I would like to add that both Chrome Dev Tools and Firefox Inspector [or whatever they call it ...] show no difference in inherited, computed, or generated styles. They appear the same in every way.
I'm just stumped. Let me know if there's other information I can provide.
Update
At your request, the compiled CSS:
.pill-menu .primary > .label:after {
border-bottom: 18px solid transparent;
border-left: 18px solid #50afdf;
border-top: 18px solid transparent;
content: "";
height: 0;
right: -1em;
position: absolute;
top: 0;
width: 0;
z-index: 1;
}
.pill-menu .primary > label {
background-color: #50afdf;
border-radius: 5px 0 0 5px;
cursor: pointer;
padding: .5em;
position: relative;
transition: all .2s ease-out;
}
It's not margins or paddings, but whitespace. Just remove the unnecessary spaces/newlines/tabs inside your label.
http://cssdeck.com/labs/v2f8qedp
<!-- Major Category
======================
--> <ul>
<li class="has-subnav primary">
<input type="checkbox" id="primary-menu" class="checkbox-toggle"/>
<label class="label" for="primary-menu"> Choose a Subject</label>
</li>
</ul>
</nav>
Tested this out on jsfiddle. Seems to solve the issue. Can you try at your end?
#-moz-document url-prefix() {
.pill-menu .primary > .label:after {
right: -.9em;
}
}

Resources