Create visual borders between elements on the same line - html

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/

Related

Create underline after last line of text to fill white space

I'm having trouble with a SCSS/CSS styling idea, I want to fill the space before or after the last line of a heading with a solid line. The last line of text does not have a set width (it varies depending on screen size) I'm open to any suggestions.
Here's what I want to achieve when the text is aligned right or left.
|Here is some text on screen| |Here is some text on screen|
|very cool -----------------| or |----------------- very cool|
| | | |
| | | |
EDIT Code added for clarity:
HTML
<h1>You're the painter, we just want to see you paint.</h1>
CSS (that is how far I've got)
h1{
font-family: "doesntMatter";
font-style: bold;
font-size: 2rem;
text-align: left;
}
h1::after{
display: inline-block;
line-height: 0;
position: relative;
bottom: 2.5rem;
border-bottom: 10px solid red;
width: 100%;
content: "";
}
I found a solution to my problem, if you take this code here and run it, the last line will be struck through.
.container {
width: 100%;
padding-inline: 2rem;
}
.text {
font-style: bold;
font-size: 2.5rem;
line-height: 2.5rem;
position: relative;
overflow-x:hidden;
}
.text::after {
position: absolute;
left:0;
bottom: 0.9rem;
width: 100%;
border-bottom: 0.4rem solid #000;
content: "";
}
<section class="container">
<h1 class="text">You're the painter, we are just the paint, brushes and canvas</h1>
</section>
But if you remove left:0; from the text::after styling, it magically jumps over to fill the blank space at the end.
I added a margin-left: 1rem to give the things some breathing room but yea I really don't know what's going on.
I don't know how it works but it just kind of does, if the .text{} element has overflow-x: hidden applied to it then the effect will cutoff at the width of the header.
.container {
width: 100%;
padding-inline: 2rem;
}
.text {
font-style: bold;
font-size: 2.5rem;
line-height: 2.5rem;
position: relative;
overflow-x: hidden;
}
.text::after {
position: absolute;
bottom: 0.9rem;
width: 100%;
margin-left: 1rem;
border-bottom: 0.4rem solid #000;
content: "";
}
<section class="container">
<h1 class="text">You're the painter, we are just the paint, brushes and canvas</h1>
</section>
That is one way to do the effect, if you want the line to spill off the page, you apply overflow-x: hidden to the .container{} element and remove if from the .text{}... since my container is 100% width the line goes off the page and works as intended.
.container {
width: 100%;
padding-inline: 2rem;
overflow-x: hidden;
}
.text {
font-style: bold;
font-size: 2.5rem;
line-height: 2.5rem;
position: relative;
}
.text::after {
position: absolute;
bottom: 0.9rem;
width: 100%;
margin-left: 1rem;
border-bottom: 0.4rem solid #000;
content: "";
}
<section class="container">
<h1 class="text">You're the painter, we are just the paint, brushes and canvas</h1>
</section>
The line responds to any changes in the width of the last line. There's a few edge cases that I'm going to have to look into like if the last line of text practically fills the entire width of the header, then there's just a little nub at the end.
But it's been fixed! I hope this helps anyone in the future that couldn't figure out the right combination of words to google to find a solution.
Building on what you have already, this snippet puts the text within a span element. This enables a white padding which can overwrite that part of the red line which is under the actual text.
h1 {
font-family: "doesntMatter";
font-style: bold;
font-size: 2rem;
text-align: left;
position: relative;
}
h1>span::after {
display: inline-block;
position: absolute;
border-bottom: 10px solid red;
width: 100%;
left: 0;
margin-top: -11px;
content: "X";
color: transparent;
z-index: -1;
}
h1>span {
background: white;
padding-bottom: 11px;
}
<h1><span>You're the painter, we just want to see you paint.</span></h1>
Note - it's a little bit hacky, including positioning 1px different from the height of the line. This is because on modern screens which use more than one screen pixel for a CSS pixel the system can 'leave behind' traces of color when it is positioning (e.g. a screen pixel - not a whole CSS pixel).

Padding on a:before pseudo element

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>

Custom Checkbox with after element - not centreing reliably

JSFiddle, won't work in Stack Snippet for some reason:
https://jsfiddle.net/m3aoswyx/2/
I have a custom checkbox, like this:
<label for="name" class="customCheckboxLabel">
<input type="checkbox" name="name" class="customCheckboxInput" />
<span>Foo</span>
</label>
With the following SCSS:
.customCheckboxLabel {
span {
font-size: 3em;
padding-bottom: 2px; //This is ignored.
}
.customCheckboxInput {
appearance: none;
-webkit-appearance: none;
-moz-appearance:none;
width: 3em;
height: 3em;
background-color: transparent;
border: 2px solid red;
border-radius: 0.5em;
transition: all 0.5s;
&:checked {
transform: rotate(45deg);
border-color: black;
&::after {
content: "\2022";
font-size: 6em;
color: #41b883;
text-align: center;
width: 100%;
height: 100%;
position: absolute;
line-height: 0.1em; //This is random
}
}
}
}
This results in a circle appearing when the box is checked, that is not quite centred within its containing square. I have been able to approximately centre it using line-height set to random values, but this value must be changed for every checkbox height/width, and after element font size. This doesn't really work for what I need. What I really want, is for the only size definition to be the font-size of the span, and the width/height of the checkbox. The after-element should simply fill the checkbox (with a small amount of padding) and be centred
Additionally, I've been trying to add a bit of padding to the bottom of the span, but this is totally ignored. I just want the span and the checkbox to be vertically aligned.
One solution for creating a centralized circle, in this case, would be to make it different using background-color, positioning, relative dimensions, auto margin and border-radius.
&::after {
content: '';
text-align: center;
width: 50%;
height: 50%;
position: absolute;
margin: auto;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: #41b883;
border-radius: 50%;
}

How to put text inside border html

#border {
position: static;
z-index: 1;
width: 120px;
height: 120px;
margin-left: 92% ;
padding: 15px;
border-radius: 11px;
background: white;
opacity: 0.2;
}
#text {
margin-left: 93%;
z-index: 2;
color: white;
font-weight: bold;
}
<div id="border"></div>
<div id="text">Users online</div>
I can't post the image here, cuz I have less than 10 reputation, so try to imagine it please. I want to place it's "Users online" inside the border, how should I do this? Thanks.
I'm assuming you are trying to have an element with a semitransparent background.
Since you are using the opacity property on the element with an id of border.
The problem here is that z-index will not have any effect, if the position is set to static, which is the default value for div elements.
The other thing is, that you should be using a relative positioned parent to make your life easier and have more control over the elements since positioned elements will leave the normal document flow and result in new stacking order.
Here you can find good information on the the z-index property, stacking and the document flow.
This is one solution to your problem.
body {
background:black;
}
.holder {
position:relative;
}
#border {
position: absolute;
z-index:1;
right:0;
width: 120px;
height: 120px;
padding: 15px;
border-radius: 11px;
background: white;
opacity: 0.2;
}
#text {
position: absolute;
z-index:2;
right:0;
width: 120px;
height: 120px;
padding: 15px;
text-align: center;
color: white;
font-weight: bold;
}
<div class="holder">
<div id="border"></div>
<div id="text">Users online</div>
</div>
But i would actually try to solve this with a different approach, because i find the above solution a bit to complex and it involves to much positioning, so if all you need is a semitransparent background just make use of the background property with an rgba value. Here is an example.
.user-panel {
float:right;
height: 120px;
width: 120px;
padding: 15px;
border-radius: 11px;
/* fallback for browser that do not support rgba */
background: #ccc;
/* semitransparent background */
background: rgba(0, 0, 0, .2);
text-align: center;
color: white;
}
/* clear the float using the pseudo after element */
user-panel:after {
clear: both;
display: block;
visibility: hidden;
height: 0px;
}
<header>
<div class="user-panel">Users online</div>
</header>
Hope that helps.
Change
position: static;
to
position: absolute;
for #border. That way, border will be "removed from the flow" (i.e. other elements will ignore it). You may need to adjust the margin-left property for #text so it properly aligns.
Fiddle: https://jsfiddle.net/xzdmLt33/1/

centering some content in a div, floating content on same line - keeping vertical alignment

I have a div with a dynamic width. In that div I'd like one block of content to be centered and another block of content to be floated to the right and to stay inline.
Not a great description, I know. Hopefully, you can get a better idea by looking here
I'd like the text to be inline with the flag.
Any suggestions?
Also I've realised my questions title is a bit horrible - suggestions for an edit welcome.
Is this what you are looking for: http://jsfiddle.net/tw16/sGC7d/ ?
.wrapper {
border: 1px solid #020202;
width:100%;
position: relative;
}
.numbers {
position: absolute;
right: 0;
top: 4px;
}
See: http://jsfiddle.net/thirtydot/zTNL8/2/
.wrapper {
border: 1px solid #020202;
position: relative
}
.flag {
display: block;
margin: 0 auto;
padding: 4px 0px;
width: 35px;
}
.flag img {
display: block
}
.numbers {
visibility: visible;
line-height: 23px;
position: absolute;
right: 0;
top: 0
}