Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extended borders with CSS

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>
like image 781
CU3ED Avatar asked Apr 20 '16 06:04

CU3ED


People also ask

How do you make a border longer in CSS?

CSS borders are placed between the margins and padding of an HTML element. If you want the borders of an HTML element to extend past the width (or height) of that element, you can add CSS padding to the element in order to push the borders outward.

Can you add 2 borders in CSS?

Multiple borders in CSS can be done by box-shadow property. Generally, we can get a single border with border property. Box-shadow property is not for multiple borders, but still, we are creating multiple borders with box-shadow property.


3 Answers

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>
like image 172
jbutler483 Avatar answered Sep 20 '22 11:09

jbutler483


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>
like image 39
Harry Avatar answered Sep 22 '22 11:09

Harry


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>
like image 33
Valentin Palkovic Avatar answered Sep 19 '22 11:09

Valentin Palkovic