Extended borders with CSS
Asked Answered
D

5

6

I've been testing an idea of extended/projecting borders with a few nested divs, and I have a working example below.

Basically, what I would like to achieve is vertical and horizontal borders that extend outside of a box with content inside. Sort of like a drafting look. I want this to be fully responsive if possible.

In my code, I have set heights with negative margins in order to get the effect I was looking for visually, but it seems like my markup is way too bloated for what I want to do. It is responsive horizontally, but vertically I just have the overflow hidden.

Another idea that went through my head while doing this is to have 4 divs, 1 for each border side (top,right,bottom,left) and then offset each div a certain amount to achieve the effect. Sort of like a "jiggled" cluster of divs. The 4 divs would be carried by a parent container AND be responsive.

Can this be done simpler than what I have in the fiddle? Is there a way to have it be flexible vertically as well as horizontally (fully responsive)? Would it be possible to have variable extensions with each border side (like 2px on one side and 4px on another)?

Without further nonsense, here's what I have so far:

body {
  margin: 0;
  padding: 0;
  width: 100%;
  font-family: Helvetica, Arial, sans-serif;
  /* text-align: center; */
}

.container {
  margin: 50px auto 0;
  padding: 0;
  width: 75%;
  height: 200px;
  position: relative;
}

.box-vert {
  margin: -10px 0;
  padding: 0;
  overflow: visible;
  height: 200px;
  position: absolute;
  border: 1px solid #C5C5C5;
  border-top: none;
  border-bottom: none;
}

.box-horz {
  height: 180px;
  margin: 10px -10px;
  overflow: visible;
  border: 1px solid #C5C5C5;
  border-left: none;
  border-right: none;
  padding: 0;
}

.box-inner {
  margin: 0 10px;
  padding: 20px;
  background-color: #ECECEC;
  height: 140px;
  float: left;
  overflow: hidden;
}

.box-inner h1 {
  margin: 0 0 10px;
  text-transform: uppercase;
  font-weight: 200;
  letter-spacing: 3px;
  font-size: 30px;
  color: #009688;
}

.box-inner p {
  margin: 0;
  line-height: 1.4;
  font-size: 14px;
  color: #666;
}
<div class="container">
  <div class="box-vert">
    <div class="box-horz">
      <div class="box-inner">
        <h1>Title Text Here</h1>
        <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Cras mattis consectetur purus sit amet fermentum. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vestibulum id ligula porta felis euismod semper.</p>
      </div>
    </div>
  </div>
</div>
Daisy answered 20/4, 2016 at 6:38 Comment(1)
You could make an image and use it as a border and just repeat it.Juvenilia
S
9

You can achieve this with a single element and a couple of pseudo elements. A quick demo can be seen below.

div {
  position: relative;
  height: 300px;
  width: 80%;
  margin: 30px;
  background: tomato;
}
div:before {
  content: "";
  position: absolute;
  top: -2px;
  left: -30px;
  width: calc(100% + 60px);
  height: 100%;
  border-top: 2px solid cornflowerblue;
  border-bottom: 2px solid cornflowerblue;
}
div:after {
  content: "";
  position: absolute;
  left: -2px;
  top: -30px;
  height: calc(100% + 60px);
  width: 100%;
  border-left: 2px solid cornflowerblue;
  border-right: 2px solid cornflowerblue;
}
<div>
  <h4>Hello, World!</h4>
  Some Text
</div>
Sulfonate answered 20/4, 2016 at 10:20 Comment(1)
Nice and simple. Thanks for your contribution. I'm going to go ahead and mark this as the answer because I think it's the simplest implementation and would work best on a larger scale, say with changes on hover, etc.Daisy
C
10

You can do this using a single element and gradients for background like in below snippet. The output is responsive (as you can see in full page view) and can adapt itself depending on the content's size.

The approach is a bit complex since it is done with a single element and so here's an explanation:

  • A padding of 15px is added to the element on all sides so as to restrict the text flow to a smaller area (that is, inside the borders that we are goind to create).
  • 4 linear gradient background images are added (one for each border) and their background size is set such that the thickness of each border is 1px but width/height of it is 100%.
  • For the top and bottom borders, the thickness/height is 1px (or whatever we need) and the width of the border will be same as container's width, so the background-size is set as 100% 1px.
  • For the left and right borders, the thickness/width is 1px and the height is 100% of the container's height, so the background-size is set as 1px 100%.
  • These gradient lines are then positioned such that they are at an offset inside the parent. That is, the top border should be offset in the y-axis by 10px (or whatever we need, but it should be less than the padding) and the left border should be offset in x-axis by 10px. Similarly the bottom and right borders should be offset from the bottom and right edge of the container by 10px and so the calc function is used to position them.
  • For the element's background, we cannot use a simple background-color with this approach as it would fill up the entire div (extending beyond the border). We cannot even use background clip, because that would clip the borders also. So, we again have to use a linear-gradient whose size is lesser than the container's dimensions by the amount of padding on all sides. So, background size for this gradient would be calc(100% - 20px) calc(100% - 20px) and positions also should be offset accordingly.
  • The border and background colors can be changed by changing the gradient's colors.

div {
  padding: 15px;
  margin-bottom: 10px;
  line-height: 1.4;
  font-size: 14px;
  color: #666;
  background: linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#ECECEC, #ECECEC);
  background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%, calc(100% - 20px) calc(100% - 20px);
  background-position: 0px 10px, calc(100% - 10px) 0px, 0px calc(100% - 10px), 10px 0px, 10px 10px;
  background-repeat: no-repeat;
}

/* Just for demo */

h1 {
  margin: 0 0 10px;
  text-transform: uppercase;
  font-weight: 200;
  letter-spacing: 3px;
  font-size: 30px;
  color: #009688;
}
body {
  margin: 0;
  padding: 0;
  width: 100%;
  font-family: Helvetica, Arial, sans-serif;
  /* text-align: center; */
}
<div>
  <h1>Title Text here</h1>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</div>

<div>
  <h1>Title Text here</h1>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has
  survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing
  software like Aldus PageMaker including versions of Lorem Ipsum.</div>

If you need variable extensions on each side, just change the padding, background size and position based on the following logic:

  • Let us assume that you need the border to extend by 6px at the top, 8px at the right, 10px at the bottom, 12px at the left and have a space of 4px between the borders and text. Then set padding using the below logic.

    padding: [border-ext-top + space-between-borders-n-text]
             [border-ext-right + space-between-borders-n-text]
             [border-ext-bottom + space-between-borders-n-text]
             [border-ext-left + space-between-borders-n-text];
  • The background image gradients (that produce the borders) are set to follow the same top-right-bottom-left order like the padding. So, set the background-position as below.

    background-position: 0px [border-ext-top], 
                         calc(100% - [border-ext-right]) 0px, 
                         0px calc(100% - [border-ext-bottom]), 
                         [border-ext-left] 0px, 
                         [border-ext-left] [border-ext-top];
  • Since padding and background-position are changed, the size of the gradient that creates the inner fill should also be changed so as to not overflow the borders.

    background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%,
                     calc(100% - [border-ext-left + border-ext-right]) calc(100% - [border-ext-top + border-ext-bottom]);

div {
  padding: 10px 12px 14px 16px;
  margin-bottom: 10px;
  line-height: 1.4;
  font-size: 14px;
  color: #666;
  background: linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#C5C5C5, #C5C5C5), linear-gradient(#ECECEC, #ECECEC);
  background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%, calc(100% - 20px) calc(100% - 16px);
  background-position: 0px 6px, calc(100% - 8px) 0px, 0px calc(100% - 10px), 12px 0px, 12px 6px;
  background-repeat: no-repeat;
}

/* Just for demo */

h1 {
  margin: 0 0 10px;
  text-transform: uppercase;
  font-weight: 200;
  letter-spacing: 3px;
  font-size: 30px;
  color: #009688;
}
body {
  margin: 0;
  padding: 0;
  width: 100%;
  font-family: Helvetica, Arial, sans-serif;
  /* text-align: center; */
}
<div>
  <h1>Title Text here</h1>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</div>

<div>
  <h1>Title Text here</h1>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has
  survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing
  software like Aldus PageMaker including versions of Lorem Ipsum.</div>
Crelin answered 20/4, 2016 at 6:49 Comment(3)
This is amazing man! Thanks for explaining so thoroughly what you have going here and the two different examples as well. Top notch.Daisy
There's a few different ways to do this as outlined by each answer. The real question is now, what is the most efficient use on a larger scale, markup-wise, etc. Basically, which is the BEST way?Daisy
@Ce. I am afraid that I can't give an impartial answer to that question. My preference would be for gradients because it needs no negative margins, no hidden overflow and keeps the pseudos for other potential uses but there is no right/wrong answer here. The best is probably what suits your site the best ;)Crelin
S
9

You can achieve this with a single element and a couple of pseudo elements. A quick demo can be seen below.

div {
  position: relative;
  height: 300px;
  width: 80%;
  margin: 30px;
  background: tomato;
}
div:before {
  content: "";
  position: absolute;
  top: -2px;
  left: -30px;
  width: calc(100% + 60px);
  height: 100%;
  border-top: 2px solid cornflowerblue;
  border-bottom: 2px solid cornflowerblue;
}
div:after {
  content: "";
  position: absolute;
  left: -2px;
  top: -30px;
  height: calc(100% + 60px);
  width: 100%;
  border-left: 2px solid cornflowerblue;
  border-right: 2px solid cornflowerblue;
}
<div>
  <h4>Hello, World!</h4>
  Some Text
</div>
Sulfonate answered 20/4, 2016 at 10:20 Comment(1)
Nice and simple. Thanks for your contribution. I'm going to go ahead and mark this as the answer because I think it's the simplest implementation and would work best on a larger scale, say with changes on hover, etc.Daisy
B
2

Another solution is to use 4 span elements inside the .container and use the before and after pseudo elements.

I have used several colors for the outbound boders, that you can understand, which css rule manipulates the borders.

The span elements are absolute positioned to the parent element. So this solution is fully responsive.

Now you can manipulate each border line seperately. Theoretically all border lines can have different height's/width's, dependending on wheter the line is a horizontal or vertical line.

body {
  margin: 0;
  padding: 0;
  width: 100%;
  font-family: Helvetica, Arial, sans-serif;
}

.container {
  margin: 50px auto 0;
  padding: 0;
  width: 75%;
  position: relative;
}
.container > span:before, .container > span:after {
  content: " ";
  display: block;
  position: absolute;
  background-color: #ccc;
}
.container > span:nth-child(1):before, .container > span:nth-child(1):after {
  width: 10px;
  height: 1px;
  left: 100%;
  background-color: red;
}
.container > span:nth-child(1):before {
  bottom: 0;
}
.container > span:nth-child(1):after {
  top: 0;
}
.container > span:nth-child(2):before, .container > span:nth-child(2):after {
  width: 10px;
  height: 1px;
  right: 100%;
  background-color: blue;
}
.container > span:nth-child(2):before {
  bottom: 0;
}
.container > span:nth-child(2):after {
  top: 0;
}
.container > span:nth-child(3):before, .container > span:nth-child(3):after {
  width: 1px;
  height: 10px;
  bottom: 100%;
  background-color: orange;
}
.container > span:nth-child(3):before {
  right: 0;
}
.container > span:nth-child(3):after {
  left: 0;
}
.container > span:nth-child(4):before, .container > span:nth-child(4):after {
  width: 1px;
  height: 10px;
  top: 100%;
  background-color: green;
}
.container > span:nth-child(4):before {
  right: 0;
}
.container > span:nth-child(4):after {
  left: 0;
}

.box-inner {
  padding: 20px;
  background-color: #ECECEC;
  height: 140px;
  border: 1px solid #ccc;
}

.box-inner h1 {
  margin: 0 0 10px;
  text-transform: uppercase;
  font-weight: 200;
  letter-spacing: 3px;
  font-size: 30px;
  color: #009688;
}

.box-inner p {
  margin: 0;
  line-height: 1.4;
  font-size: 14px;
  color: #666;
}
<div class="container">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <div class="box-inner">
    <h1>Title Text Here</h1>
    <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Cras mattis consectetur purus sit amet fermentum. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vestibulum id ligula porta felis euismod semper.</p>
  </div>
</div>
Bosson answered 20/4, 2016 at 7:4 Comment(0)
K
0

You can also use , background-clip aside background-image (gradients), background-size:

https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip

https://developer.mozilla.org/en-US/docs/Web/CSS/background-size

https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient

div {
  width:400px;/* whatever*/
  padding:20px;/* you need this ! use same units as for bg-position for better control  */
  margin:2em;/* whatever */
  background:/* draw images needed  to fake borders and bg-color */ 
    linear-gradient(to top, black,black) 1em 0 repeat-y ,
    linear-gradient(to top, black,black) calc( 100% - 1em) 0 repeat-y,
    linear-gradient(to left, black,black) 0 1em repeat-x,
    linear-gradient(to left, black,black) 0 calc(100% - 1em)  repeat-x ,
    linear-gradient(30deg,gray,lightgray) no-repeat;
  
  background-size: 3px 100%, 3px 100%, 100% 3px ,100% 3px , auto auto ;
  background-clip: border-box,border-box,border-box,border-box,content-box;
}
/* add some contet in html to test behavior , you may style it too */
p {
  margin:0;
  padding:0.5em;
  text-align:justify
}
<div>
 <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit met isi.</p>
</div>

very similar to harry actually, just different from the background-clip properties used to draw the background-color via a gradient only inside the content area.

Kalinda answered 20/4, 2016 at 19:57 Comment(0)
F
-1
<ul>
<li><img src="#" class="logo"></li>
</u
Felid answered 24/4, 2021 at 2:25 Comment(1)
please do not post only code , Add a description for more helpCigarillo

© 2022 - 2024 — McMap. All rights reserved.