Border bottom with fixed size - html

What is the best way to add a small border at the bottom of a text?
The border has to be centered and maximum 20px, but the text can be very long, even 200px.
So it's like:
<h1>This text can be longer than the border</h1>
<style>
.h1 {border-bottom:8px solid #000;}
</style>
Should I add a div after my h1 and set a maximum size for it?

you can use pseudo element ::after and use left:50% / transform:translateX(-50%) to align in the middle no matter the width
h1 {
position: relative;
display:inline-block;
/* min-width:200px */
}
h1::after {
border-bottom: 1px solid red;
bottom: -10px;
content: "";
height: 1px;
position: absolute;
width: 20px;
left:50%;
transform: translateX(-50%);
}
<h1>This text can be longer than the border</h1>

Using Linear Gradients for Background:
Or you can also do this using linear-gradient background images. Advantage of using a gradient is that it doesn't require any extra pseudo-elements which can be used for other purposes. The border's thickness is based on the background-size in Y-axis and the width of the border is based on the size in X-axis. The background-position property is used to center the border.
The disadvantage is the relatively poor browser support for linear-gradient as compared to pseudo elements. Gradients are supported only in IE10+.
h1 {
display: inline-block;
padding-bottom: 4px; /* to give some gap between text and border */
background: linear-gradient(to right, black, black);
background-repeat: no-repeat;
background-size: 20px 2px;
background-position: 50% 100%;
}
<h1>This text can be longer than the border</h1><br>
<h1>Some text with lesser length</h1><br>
<h1>Some text</h1>
Using a Pseudo-element:
You can do this using a pseudo-element. By adding a pseudo-element with 20px width, positioning it absolutely we will be able to produce the required effect. The left: 50%, translateX(-50%) is used to position the pseudo-element at the center. The height of the pseudo-element determines border's thickness while the background determines the color of the border.
Advantage of this is the browser support as it should work in IE8+.
h1 {
position: relative;
display: inline-block;
padding-bottom: 4px; /* to give some gap between text and border */
}
h1:after {
position: absolute;
content: '';
left: 50%;
bottom: -2px;
width: 20px;
height: 2px;
background: black;
transform: translateX(-50%);
}
<h1>This text can be longer than the border</h1>
<br>
<h1>Some text with lesser length</h1>
<br>
<h1>Some text</h1>

Improving the answer of dippas, you can see when you use bigger widths, the border of the after elements is innacurate. You can prevent this by using calc(50% - 100px); instead of 50% whereas the 100px are half the width of the after element.
.bottom-border {
position: relative;
display:inline-block;
}
.bottom-border::after {
border-bottom: 2px solid red;
bottom: -10px;
content: "";
height: 1px;
position: absolute;
width: 200px;
left: calc(50% - 100px);
transform: translateY(-50%);
}
<p class="bottom-border">
Hi, i am a quite long text, might be 200px, probably more i guess, but nobody knows really.
</p>

Related

How to position a background on one side of centered content while making the BG translucent without distortion?

I'm working on the following layout issue: the page heading is center aligned. It should have a background image on its left side, and the background should also be made semi-transparent. The heading content may be of various lengths; the positioning of the background needs to take this into account. The layout should be the same on both desktop and mobile. For example:
So far, I've been able to make the background image semitransparent and center it by using the ::after pseudo-element. The image is set as the background of the ::after, and justification on the parent also positions the background. Code so far:
.heading-bg-logo {
display: flex;
justify-content: center;
color: blue;
}
.heading-bg-logo::after {
content: "";
display: inline-block;
width: 1em;
height: 1em;
background: url(https://images.unsplash.com/photo-1581079289196-67865ea83118?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=120&q=80);
background-repeat: no-repeat;
background-size: 100%;
position: absolute;
z-index: -1;
opacity: 0.2;
}
<h2 class="heading-bg-logo">
Test Heading
</h2>
The issue at this point is that the logo positioned in the center behind the heading, rather than the left side of the heading text. How can I position it on the left side of the content?
Second Issue which i have is that the Logo Size should be customizable.
Note: I've used a demo image here from Unsplash.
Background sizing and positioning by themselves shouldn't require more than background properties on the element itself. As long as you can get the content box to shrink to fit the content, background-origin can be used to position the background relative to the content box (or the padding box, if you want the background to extend beyond the content box). However, requiring additional transparency on the background steers this towards a pseudo-element.
An alternative to a pseudo-element that can be used in certain circumstances is to use an inset box-shadow with a partially transparent color to wash-out the image. This only works if the background image is on top of a solid color; the same color is then used as the box-shadow color. Note the transparency of the box-shadow is the inverse of the transparency for the image: the more "transparent" the background is supposed to be, the less transparent the box-shadow color.
The other tricky aspect is in how you shrinkwrap the content. The simplest is to use a width of fit-content, though it's not supported in older browsers:
.heading-bg-logo {
color: blue;
width: fit-content;
margin: auto;
padding: 0 0.5em;
/* The spread-radius needs to be large enough to cover the background */
box-shadow: 0 0 0 1000px inset rgba(255, 255, 255, 0.8);
background: url("https://images.unsplash.com/photo-1581079289196-67865ea83118?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3269&q=80");
background-origin: padding-box;
background-repeat: no-repeat;
background-size: contain;
}
<span>content before</span>
<h2 class="heading-bg-logo">Test Heading</h2>
<span>content after</span>
Note that a content-size of contain is used with the sample image to scale it to fit within the element without distorting the aspect ratio.
If using a pseudo-element to achieve semitransparency, then you can position it relative to the content using the usual approach: relatively position the parent element and absolutely position the pseudo-element:
.heading-bg-logo {
color: blue;
width: fit-content;
margin: auto;
position: relative;
}
.heading-bg-logo::after {
content: " ";
opacity: 0.2;
background: url("https://images.unsplash.com/photo-1581079289196-67865ea83118?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3269&q=80");
background-repeat: no-repeat;
background-size: contain;
position: absolute;
top: 0;
left: -0.5em;
height: 100%;
width: 100%;
z-index: -1;
}
<span>content before</span>
<h2 class="heading-bg-logo">Test Heading</h2>
<span>content after</span>
Fast fix. Add margin-right: 150px; to your .heading-bg-logo::after class.
Update (responsive behavior)
.c {
display: flex;
justify-content: center;
align-items: center;
}
.c h2 {
color: blue;
}
.heading-bg-logo {
position: relative;
}
.heading-bg-logo::after {
position: absolute;
top:-20px;
content: "";
margin-left: -80px;
width: 120px;
height: 40px;
background: url(https://images.unsplash.com/photo-1581079289196-67865ea83118?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3269&q=80);
background-repeat: no-repeat;
background-size: 100% 95%;
z-index: -1;
opacity: 0.2;
}
<div class="c">
<div class="heading-bg-logo"></div>
<div>
<h2>Test Heading Test Heading</h2>
</div>
</div>
<div class="c">
<div class="heading-bg-logo"></div>
<h2>Test Heading </h2>
</div>
.heading-bg-logo {
display: flex;
justify-content: center;
color: blue;
}
.heading-bg-logo::after {
content: "";
display: inline-block;
width: 120px;
height: 40px;
margin-right: 150px;
background: url(https://images.unsplash.com/photo-1581079289196-67865ea83118?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3269&q=80);
background-repeat: no-repeat;
background-size: 100% 95%;
position: absolute;
z-index: -1;
opacity: 0.2;
}
<h2 class="heading-bg-logo">
Test Heading
</h2>

Creating connectors between <div> boxes

I've been trying to create a gray connector between div containers (image below) for a while now. The margin between the containers is set to 2.5vw per container on each side.
I've tried to create it using an .svg background on a :before pseudo element and positioning it, but I couldn't make it work. The gray connector should stay fixed in relation to the boxes until the boxes wrap (mobile version), in which case the connectors should be hidden. The mobile version is easy to setup, but when the elements are next to each other I'm finding it almost impossible to apply the gray connector to the elements. The connector should stay fixed in relation to the containers when transitioning between laptop screens and large desktop screens.
Here's the outcome I want:
Gray connector between boxes.
Here's the outcome I've got and the code I've used:
Outcome I've got.
.box-container:after{
content: '';
height: 700px;
width: 600px;
position: absolute;
background-image: url("folder_path/Connector-1.svg");
background-repeat: no-repeat;
background-position: -80px 60px;
background-overflow: visible !important;
z-index: 0 !important;
}
.box-container{
z-index: 1 !important;
}
Maybe I've been going at it the wrong way, all workarounds are welcome.
Here is one way to do it:
main {
width: 100%;
height: 100%;
position: relative;
}
section {
display: inline-block;
width: 100px;
height: 200px;
background: orange;
box-shadow: 0 5px 15px rgba(0, 0, 0, .3);
}
section + section {
margin-left: 46px;
}
.connector {
position: absolute;
top: 0;
z-index: -1;
background: #444;
width: 100px;
height: 200px;
transform-origin: top left;
transform: skewX(36.87deg); /* do some trigonometry here to get the deg */
}
.connector:nth-of-type(2) {
left: 150px;
}
<main>
<section></section>
<section></section>
<section></section>
<div class="connector"></div>
<div class="connector"></div>
</main>
I figured out the solution! It's to create a pseudo-element, with a height of 100% and a width equal to the margin between the elements. To keep it responsive, it's important to use vw for the width unit, both for the margin between elements and also the width of the decoration itself. The margin of the <div>s are 2.5vw each, so setting the width of the pseudo element to 5 makes it fit perfectly. Heres the code:
.container:after{
content: '';
z-index:-1;
position: absolute;
top: 0;
right: -5vw;
width: 5vw;
height: 100%;
background-color: #444;
clip-path: polygon(0% 0%, 100% 40%, 100% 100%, 0% 60%);
}

How to create div with pseudo elements directly on top & under?

I'm trying to create a div with a triangle on top & a triangle under it..
the div should be responsive in size, so not a fixed width
not a fixed height either
Already experimented with borders only but they don't seem to give me that flexible width I want..
So where I'm at:
I'm using pseudo elements to place svgs I made of the shape!
Problem is, I'm not sure how to place them properly.. feels so strange to have to set 100% from top to place the bottom one & the other way (but as you can see there is a line in between etc)..
Here's the fiddle:
https://jsfiddle.net/benvanlooy/c4vqb1ay/
.box {
position: relative;
display: inline-block;
width: 40%;
background-color: #D01417;
margin-top: 200px;
margin-bottom: 200px;
padding: 30px;
}
.box::before {
content: url('http://www.benvanlooy.be/fiddle/box-triangle-top-red-new-01.svg');
position: absolute;
width: 100%;
left: 0px;
bottom: 100%;
}
.box::after {
content: url('http://www.benvanlooy.be/fiddle/box-triangle-bottom-red-new-01.svg');
position: absolute;
width: 100%;
left: 0px;
bottom: 0px;
top: 100%;
}
<div class="box">
this is some content
<BR/> this
<br/> box
<br/> has
<br/> a <br/> variable
<br/> height
</div>
Has anyone got any experience with something like this? :-)
The answer is probably easy, so I'm feeling rather stupid :/
Any help would be much appreciated!
You can use gradient and no need for complex code and extra SVG:
.box {
position: relative;
display: inline-block;
width: 40%;
background:
linear-gradient(to top right,#D01417 49.5%,transparent 50%) top right/50.2% 200px,
linear-gradient(to top left,#D01417 49.5%,transparent 50%) top left/50.2% 200px,
linear-gradient(to bottom right,#D01417 49.5%,transparent 50%) bottom right/50.2% 200px,
linear-gradient(to bottom left,#D01417 49.5%,transparent 50%) bottom left/50.2% 200px,
linear-gradient(#D01417,#D01417) center/100% calc(100% - 400px);
background-repeat:no-repeat;
padding: 200px 30px;
}
<div class="box">
this is some content
<br> this
<br> box
<br> has
<br> a <br> variable
<br> height
</div>
This creates visual triangles without any images (using borders only):
.box {
position: relative;
display: inline-block;
width: 40%;
background-color: #D01417;
margin-top: 200px;
margin-bottom: 200px;
padding: 30px;
}
.box::before {
content: "";
display: block;
position: absolute;
left: 50%;
top: -40px;
transform: translateX(-50%);
border-width: 22px;
border-color: transparent transparent #D01417 transparent;
border-style: solid;
}
.box::after {
content: "";
display: block;
position: absolute;
left: 50%;
bottom: -40px;
transform: translateX(-50%);
border-width: 22px;
border-color: #D01417 transparent transparent transparent;
border-style: solid;
}
<div class="box">
this is some content
<BR/> this
<br/> box
<br/> has
<br/> a <br/> variable
<br/> height
</div>
You can remove a 4 px line by using calc like this:
.box::before {
bottom: calc(100% - 4px);
}
https://jsfiddle.net/c4vqb1ay/33/
or
https://jsfiddle.net/c4vqb1ay/36/
Another option would be to clip the actual div's shape, without using pseudo elements or SVGs. For example:
div {
background-color: #D01417;
width: 40%;
clip-path: polygon(0 3em,
50% 0,
100% 3em,
100% calc(100% - 3em),
50% 100%,
0 calc(100% - 3em)
);
padding: 4em 1em;
}
html * {
box-sizing: border-box;
}
<div>
this is some content<BR/>
this<br/>
box<br/>
has<br/>
a <br/>
variable<br/>
height
</div>
Browser support for clip-path: https://caniuse.com/#feat=css-clip-path
(works in most current browsers except Edge, if you add a -webkit- prefix)
The polygon is drawn by simply defining it's points:
translates to CSS shape as:
0 3em,
50% 0,
100% 3em,
100% calc(100% - 3em),
50% 100%,
0 calc(100% - 3em)
(starting at top left, but it doesn't really matter)
If you ever decide to go for more complex shapes, this tool is quite useful: https://bennettfeely.com/clippy/

Combine div border with image background

I want to achieve something like this:
The width of the element is 100%. I will use only the centered corner and combine with border-top:
.element {
border-top: solid 1px #ccc ;
background: url('../images/arrow.png') no-repeat center top;
}
But the border stays inside the arrow. I tried up image background -1px to hide the border but it didn't work. How do I do this?
I solved it with an extra container:
HTML:
<div class="first"><div class="second"></div></div>​
CSS:
.first {
border-bottom: 5px solid #000;
width:100px;
height:100px;
background-size: 20%;
background-position:50% 105%;
box-sizing: border-box;
}
.second {
width:100%;
height:104px;
background: url(https://encrypted-tbn3.google.com/images?q=tbn:ANd9GcROusF7rh7H4mWpr8wQIllxWPAHHIShRyG62xp3qy2O4Av_NmNV) no-repeat;
background-size: 20%;
background-position:50% 100%;
}
​
jsfiddle: http://jsfiddle.net/AKpLT/
Interesting issue. Here's one contrived solution using the :before selector to absolute position the image over the border. See this jsfiddle for a working example. The relevant code is as follows:
div {
border: 1px solid red; /* For demo purposes it's red */
position: relative;
}
div:before {
content: url('http://i.stack.imgur.com/P3zMs.png');
position: absolute;
top: -1px;
width: 100%;
text-align: center;
line-height: 1px;
}
Here's a screenshot of the result:
Edit: the browser compatability for the :before selector tells us it's only supported in IE8 and higher. It's even worse though, because as far as I can tell the content: url(...) construct nor the background-image of a :before pseudo-element doesn't seem to work even in IE9. Fortunately, this should fall under graceful degredation...
If you're already creating the image just make the entire thing your background image in the shape you want it. Make it long enough so it can adjust to whatever reasonable length element you might want to put it in.
Like Mash I'd use another element for the background, but unlike Mask I'd use the CSS :before or :after pseudo elements:
<h2>Heading</h2>
h2 {
border-top: 1px solid #ccc;
position: relative;
}
h2:after {
background: url(IMAGE);
content: " ";
display: block;
width: WIDTH-OF-IMAGE;
height: HEIGHT-OF-IMAGE;
position: absolute;
left: 50%;
top: -1px;
margin-left: -WIDTH-OF-IMAGE/2;
}

How to apply an opacity without affecting a child element with html/css?

I want to achieve this using html and css:
I have tried to set the opacity of the container to 0.3 and the box to 1, but it doesn't work: both divs have 0.3 opacity.
jsFiddle of my try here
The effect I am trying to achive is a popup box that comes on top of the page. It is highlighted by fading the content below (by lowering the opacity).
You can use opacity in combination with background color, like this:
#container {
border: solid gold 1px;
width: 400px;
height: 200px;
background:rgba(56,255,255,0.1);
}
#box {
border: solid silver 1px;
margin: 10px;
width: 300px;
height: 100px;
background:rgba(205,206,255,0.1);
}
<div id="container">
containter text
<div id="box">
box text
</div>
</div>
​Live demo
As far as I know you can't do it in a simple way. There a couple of options here:
Use absolute positioning to position box "inside" the container.
#container {
opacity: 0.3;
background-color: #777788;
position: absolute;
top: 100px;
left: 100px;
height: 150px;
width: 300px;
}
#box {
opacity: 1;
background-color: #ffffff;
position: absolute;
top: 110px;
left: 110px;
height: 130px;
width: 270px;
}
<div id="container"></div>
<div id="box">
<p>Something in here</p>
</div>
Use Javascript - almost the same as above, but position and size don't have to be hardcoded.
You can't apply an opacity property without affecting a child element!
"Opacity applies to the element as a whole, including its contents, even though the value is not inherited by child elements. Thus, the element and its children all have the same opacity relative to the element's background, even if they have different opacities relative to one another... If you do not want to apply opacity to child elements, use the background property instead." https://developer.mozilla.org/en-US/docs/Web/CSS/opacity
If you want the opacity to be applied only to the background, without affecting the child elements, use:
background-color: rgba(255, 255, 255, .3)
However, you can achieve the desired effect if you place them inside a div parent element and use CSS position property:
.parent {
border: solid green 3px;
position: relative;
width: 400px;
height: 200px;
}
.sibling-one {
border: solid red 3px;
position: absolute;
box-sizing: border-box;
width: 400px;
height: 200px;
opacity: .3;
}
.sibling-two {
border: solid blue 1px;
margin: 10px;
width: 200px;
height: 100px;
position: absolute;
transform: translateY(50%);
}
<div class="parent">
<div class="sibling-one">
<p>A sibling's one element</p>
</div>
<div class="sibling-two">
<p>A sibling's two element</p>
</div>
</div>
Try using rgba as a 'pre content' overlay to your image, its a good way to keep things responsive and for none of the other elements to be effected.
header #inner_header_post_thumb {
background-position: center;
background-size: cover;
position: relative;
background-image: url(https://images.pexels.com/photos/730480/pexels-photo-730480.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
border-bottom: 4px solid #222;
}
header #inner_header_post_thumb .dark_overlay {
position: relative;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.75);
}
header #inner_header_post_thumb .dark_overlay .container .header-txt {
padding-top: 220px;
padding-bottom: 220px;
color: #ffffff;
text-align:center;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt h1 {
font-size: 40px;
color: #ffffff;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt h3 {
font-size: 24px;
color: #ffffff;
font-weight: 300;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt p {
font-size: 18px;
font-weight: 300;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt p strong {
font-weight: 700;
}
<header>
<div id="inner_header_post_thumb">
<div class="dark_overlay">
<div class="container">
<div class="row header-txt">
<div class="col-xs-12 col-sm-12">
<h1>Title On Dark A Underlay</h1>
<h3>Have a dark background image overlay without affecting other elements</h3>
<p>No longer any need to re-save backgrounds as .png ... <strong>Awesome</strong></p>
</div>
</div>
</div>
</div>
</div>
</header>
See a working codepen here
Using background-color: rgba(#777788, 0.3); instead of opacity could maybe fix the problem.
Apply this css rule
.alpha60 {
/* Fallback for web browsers that doesn't support RGBa */
background: rgb(0, 0, 0);
/* RGBa with 0.6 opacity */
background: rgba(0, 0, 0, 0.6);
/* For IE 5.5 - 7*/
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);
/* For IE 8*/
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";
}
In addition to this, you have to declare background: transparent for IE web browsers.
For more details visit the following link:
http://robertnyman.com/2010/01/11/css-background-transparency-without-affecting-child-elements-through-rgba-and-filters/
Any child of an element with opacity set will take on that opacity.
To achieve this style you could use rgba colours and filters for IE for the background, and opacity on the textual elements. So long as the second box isn't a child of one of the text elements, then it won't inherit the opacity.
Another workaround is to simply use an overlay background to create a similar effect.
I personally like a black overlay with about a 65% opacity, but for what you are trying to do you may want to use a white overlay at round 70%.
Create a small (100 x 100 or less) PNG in Photoshop or GIMP that has the color and opacity you want. Then just set that as the background of your light box.
If you create multiple PNGs at different opacities you can easily switch between them with JS or dynamically at load via backend scripting.
It's not technically what you are trying to do, but aesthetically it can give a very similar effect and UX wise accomplishes the same thing. It is also very easy to do, and widely supported across pretty much everything.
Opacity will always inherits by the child element regardless whatever the element in there, there is no workaround up to today have suggested, when the moving of the child element outside the transparency background is not an option like in a popup menu/dialog box creation, use of background with the rgba is the solution.
Here is a input box that i created that i can turn on or off with the class property invisible by javascript
<div id="blackout" class="invisible">
<div id="middlebox">
<p>Enter the field name: </p>
<input type="text" id="fieldvalue" />
<input type="button" value="OK" id="addfname" />
</div>
</div>
CSS
#blackout {
z-index: 9999;
background: rgba(200, 200, 200, 0.6);
height: 100%;
width: 100%;
display: block;
padding: 0px;
clear: both;
float: left;
position: absolute;
margin-top: -10px;
margin-right: 0px;
margin-bottom: 0px;
margin-left: -10px;
}
#blackout #middlebox {
border: thick solid #333;
margin: 0px;
height: 150px;
width: 300px;
background-color: #FFF;
top: 50%;
left: 50%;
position: absolute;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
padding: 10px 50px 0px 50px;
}
#middlebox p {
float: left;
width:100%;
clear:both;
}
#middlebox input {
clear:both;
margin-bottom:10px;
}
#middlebox input[type=text]{
width:100%;
}
#middlebox input[type=button]{
float:right;
width:30%;
}
.invisible{
visibility:hidden !important;
}
Use such elements that you can add :before or :after. My solution
<div class="container">
<div>
Inside of container element is not effected by opacity.
</div>
</div>
Css.
.container{
position: relative;
}
.container::before{
content: '';
height: 100%;
width: 100%;
position: absolute;
background-color: #000000;
opacity: .25
}
This might not be the most orthodox method but you can use a small semi-transparent background image for each div / container that repeats. It does seem that in this day and age you should be able to achieve this in pure (simple not hackish) css with no js but as the answers above show it isn't that straight forward...
Using a tiled image might seem dated but will work no worries across all browsers.
You can add a container's sibling absolutely positioned behind container, with the same size, and apply opacity to it.
And use no background on your container.
Now container's children have no opaque parent and the problem vanishes.