Padding on a:before pseudo element - html

I am trying to style some links with lines underneath using the :before pseudo element. The link element has some padding that I cannot change. I have set the before position to absolute to show the line, but as I understand, this means the padding of the link gets counted as part of the :before element width. I have tried using box-sizing: content-box; but the padding space still gets included.
What I trying to achieve is for the line to only go as far as the link text and not into the padding space.
HTML:
<div>
heya
what's up?
</div>
CSS:
a{
text-decoration: none;
color: black;
position: relative;
padding: 1em;
}
a::before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
background-color: #000;
}
jsfiddle
Thanks

use the css calc
as : width: calc(100% - 2em);
here is the fiddle : https://jsfiddle.net/hellooutlook/krgLeq6h/1/

You could use the left and right properties (matching the x-padding of your anchor) and drop the width:
a {
text-decoration: none;
color: black;
position: relative;
padding: 1em;
}
a::before {
content: "";
position: absolute;
height: 2px;
bottom: 0;
background-color: #000;
left: 1rem;
right: 1rem;
}
<div>
heya
what's up?
</div>

Do it with background and you will have better control:
a {
text-decoration: none;
color: black;
padding: 1em;
background:
linear-gradient(#000,#000)
bottom -0.5em center /* position */
/100% 2px /*width height */
no-repeat;
background-origin:content-box; /* this will consider only the content and not the padding */
}
<div>
heya
what's up?
</div>

Related

Why is it invalid when setting the background color for ul tag?

I'm using ul tag to create a dropdown in vue, but I don't know why setting the background doesn't work.I haven't set the style of li tag.
HTML
<div
class="lang-dropdown"
#mouseover="langActive = true"
#mouseleave="langActive = false"
>
<ul>
<li v-for="k in [1, 2, 3]" class="lang-option"></li>
</ul>
</div>
SCSS
.lang-dropdown {
position: absolute;
z-index: 4;
background: transparent;
margin-top: 20px;
padding-top: 8px;
min-width: 90px;
height: 90px;
ul {
list-style: none;
width: 100%;
height: 100%;
border-radius: 15px;
padding: 0;
margin: 0;
background: black;
color: #2c3e50;
cursor: pointer;
}
}
I think that white area is another white element (for example an absolute element) that is positioned on the top layer of ul
I found the reason, the absolute position element was obscured by the upper div.

Overflowing Underline While Being Responsive to Text Length

I'm trying to emulate this effect via CSS:
The reason this is an issue is because it needs to be re-usable. The red underline's size should be dictated by the text length, but also overflow its container in a predictable manner, e.g.:
<div>
<h1>This</h1>
<h1>Cool</h1>
<h1>Effect</h1>
</div>
The red underline should extend outside the div by 10px on the left, and then also overflow the text itself by roughly 50px on the right. So, all told, the red line is +60 pixels wider than the text itself.
How can I achieve this effect without doing it manually each time? I've had no success with pseudo elements, and box-shadow won't extend on the left and right as I need it to.
Pseudo elements was the answer for me. Setting z-index on the :after element to get it positioned behind the parent element is a neat trick. The elements can't be block elements, but other than that it seemed straightforward.
html {
min-height: 100%;
}
body {
min-height: 100%;
background: linear-gradient(to bottom, #0b122f 0%, #17457d 100%);
padding: 20px;
}
h1 {
position: relative;
display: inline-block;
color: #fff;
font-family: sans-serif;
font-size: 100px;
font-weight: 300;
margin: 0;
}
h1:before {
content: "";
background: red;
height: .25em;
width: calc( 100% + 60px);
position: absolute;
bottom: .15em;
left: -10px;
z-index: -1;
}
<div>
<h1>This</h1>
<br />
<h1>Cool</h1>
<br />
<h1>Effect</h1>
</div>
use <h1><span>This</span></h1> make effect in span and adjust red box to use padding to were's you want :
h1 span {
position: relative;
font-size: 100px;
font-weight: 300;
margin: 0;
padding:0 0 0 20px;
}
h1 span::before {
content: "";
background: red;
height: .25em;
position: absolute;
bottom: .15em;
z-index: -1;
width: 100%;
left: 0;
}
like: https://jsfiddle.net/bdmpqkme/1/
All this examples mentioned above by lalit bhakuni and JasonB work really well, but only when you don't have any section with a background behind this underlined text.
The z-index: -1 will put the line you want behind the text like you want and also behind any other parent sections. In case any of these parent sections have a background, the line will be hidden (behind).
Other solution, not so clean, but solves all our problems is by adding an extra element inside of your heading:
HTML
<div class="div-with-background">
<h1><span>This</span></h1>
<br />
<h1><span>Cool</span></h1>
<br />
<h1><span>Effect</span></h1>
</div>
CSS
.div-with-background {
background-color: #333;
}
h1 {
position: relative;
display: inline-block;
color: #fff;
font-family: sans-serif;
font-size: 100px;
font-weight: 300;
margin: 0;
}
h1::before {
content: "";
background: red;
height: .25em;
width: calc( 100% + 60px);
position: absolute;
bottom: .15em;
left: -10px;
}
h1 > span {
position: relative;
}
In this case, we don't even need to use the z-index property.

Create visual borders between elements on the same line

I'd like the have a visual border, pipe or some other separator between the <span> elements in the following snippet. The trouble is that when they flow into a new line I end up with a border at the beginning of the line. How can i apply some kind of border between elements only when they are on the same line? I am completely open to changing the markup or taking another approach, however I've tried a number of things from flexbox to floats so far without success.
Stipulations:
I do not want to use javascript for this.
span content is dynamic so media queries won't work since I can't know the width of the elements or where they might break.
Is this even possible? I've already looked at this similar question but the answers there either use js or media queries.
The snippet below is a basic example and I've put the spans in a resizeable div only to demonstrate the flow problem at smaller widths.
.resizable {
resize: horizontal;
overflow: scroll;
border: 1px solid black;
height: 95vh;
box-sizing: border-box;
min-width: 120px;
max-width: 100%;
padding: 10px;
}
span {
font-size: 18px;
font-family: sans-serif;
}
span+span {
margin-left: 10px;
border-left: 2px solid #aaa;
padding-left: 10px;
display: inline-block;
}
<div class="resizable">
<span>dog</span><span>cat</span><span>elephant</span><span>potato</span><span>boston clam chowder</span>
</div>
You can fix this by using a container with the overflow hidden, and a negative margin to “drag” the elements at the beginning of the line outside of that overflow area.
(In this particular example the overflow:hidden is not really necessary, the outer scrolling element already takes care of that, but in different scenarios it might be needed.)
The 1.5em value used here is a bit of a magic number; you might want to replace it with a pixel value, since you’re using pixels for the border and its spacing from the text already - but in general, you should be able to find “working” values with a little bit of experimentation.
.resizable {
resize: horizontal;
overflow: scroll;
border: 1px solid black;
height: 95vh;
box-sizing: border-box;
min-width: 120px;
max-width: 100%;
padding: 10px;
}
.container {
margin-left: -1.5em;
width: calc(100% + 1.5em);
}
span {
font-size: 18px;
font-family: sans-serif;
margin-left: 10px;
border-left: 2px solid #aaa;
padding-left: 10px;
display: inline-block;
}
<div class="resizable">
<div class="container">
<span>dog</span><span>cat</span><span>elephant</span><span>potato</span><span>boston clam chowder</span><span>dog</span><span>cat</span><span>elephant</span><span>potato</span><span>boston clam chowder</span><span>dog</span><span>cat</span><span>elephant</span><span>potato</span><span>boston clam chowder</span>
</div>
</div>
Here's a pure CSS method that also works for elements that are centered.
The ::before and ::after of adjacent tiles are used to create a dark strip between the elements, then, the ::before of the container clips the lighter stuff out of existence.
Downsides - Getting the perfect color can be tricky as there's lots of maths involved.
section {
text-align: center;
position: relative;
}
section::before {
/* Clip light areas to pure white, leaving only boarders*/
mix-blend-mode: color-dodge;
background: #bbb;
z-index: -1000;
/* Fill Parent */
display: block;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
content: "";
}
span {
position: relative;
display: inline-block;
box-sizing: border-box;
padding: 10px;
}
/* Spans slightly overlap creating darker lines between elements*/
span::before {
left: -1px;
}
span::after {
right: -1px;
}
span::before, span::after {
position: absolute;
content: "";
display: block;
width: 10px;
height: 100%;
background: #555;
top: 0;
z-index: -1001;
mix-blend-mode: multiply;
}
<section>
<span>Hello</span><span>Cats</span><span>Fish</span><span>Dogs</span><span>Hello</span><span>Cats</span><span>Fish</span><span>Dogs</span><span>Hello</span><span>Cats</span><span>Fish</span><span>Dogs</span>
</section>
For some reason, this code does not work in Stackoverflow's JSFiddle. Here's a link to JSFiddle where it does work:
https://jsfiddle.net/mdsimmo/vwu7xbjp/2/

how to create div caption similar to form label with knockout of background div border

is there a way to achieve div caption similar to form label (placed in the middle of border), but with knockout of div border? the problem is that i can`t simply use background color for H1 (caption) element, as i have a gradient background image applied at the always visible body element.
the code:
#text_caption {
border-bottom: 2px solid #838383;
margin-top: 30px;
position: relative;
}
#text_caption H1 {
padding: 0 10px;
position: absolute;
top: -45px;
}
<div id="text_caption">
<h1>inspirations to seeing and doing</h1>
</div>
Almost everything works great, except that i need to knockout div border by H1 element to make background image upper in the DOM visible.
jsfiddle example:
http://jsfiddle.net/petko3000/crkstrah/
Thank you for your help.
Did not quite get your question, but if you wanted it to look like this:
------- H1 Header with text -------
You can try the following:
<html>
<head>
<style>
h1:after { margin-left: 2%; }
h1:before { margin-left: -52%; width: 48%; text-align: right; }
h1:before, h1:after {
position: absolute;
top: 51%;
margin-top: -1px;
overflow: hidden;
width: 50%;
height: 1px;
content: '\a0';
border-bottom: 3px solid black;
}
h1 { margin: 0.5em 0 0.1em; position: relative; z-index: 1; overflow: hidden; text-align: center; }
</style>
</head>
<body>
<h1>Inspirations to seeing and doing</h1>
</body>
</html>

Content not sitting in front of element behind content HTML

http://fiddle.jshell.net/hutber/uAczq/ Is the easiest way to explain it.
/html
<div title="1%">
1%
<div class="background rating_90"></div>
</div>
//css
.rating {
display: block;
width: 100%;
height: 18px;
line-height: 18px;
border: 1px solid #7F7F7F;
position: relative;
text-align: center;
border-radius: 3px;
}
.rating .background.rating_90 {
width: 90%;
}
.rating .background {
height: 100%;
position: absolute;
top: 0;
left: 0;
content: "";
background-color: #75890C;
border-right: 1px solid #7F7F7F;
}
Currently, the text inside the will not be visible, instead .background sits in front of the text.
I don't want to add another element inside of the parent div
Use z-index: -1.
z-index can only be used on explicitly positioned elements. That means anything with position: relative; or position: absolute; can be positioned on the Z pane, or for a better understanding, the "depth" level within a page.
Do:
.rating .background {
z-index: -1;
/* The rest of your CSS */
}
You can also remove content: ''; as it has no effect on non-pseudo selectors.
See Fiddle here.
Firstly, you do not need the content property as this is not a pseudo element.
However, you need to set the z-index of the bg div
JSfiddle Demo
CSS (extract)
.rating .background {
z-index:-1; /* add this */
}