0

I don't really understand the reason behind this behavior: http://codepen.io/gasim/pen/NPyjXB. I am trying to create an angled border with ::before, ::after selectors. The layout is in the following way:

<div class="container">
   <div class="side left"></div>
   <div class="text">Hello World</div>
   <div class="side right"></div>
</div>

The end of left side and the beginning of right side should have angled borders. So, I decided to use ::before and ::after since it gives me much more power on what I want to show:

.side {
   position: relative;
   width: 20%;
}

.side.left::after {
  content: "";
  position: absolute;
  top: 0;
  right: -15px;
  width: 20px;
  height: 50px;
  background: #1EAFEF;
  -webkit-transform: skewX(15deg);
}

.side.right::after {
  content: "";
  position: absolute;
  top: 0;
  left: -15px;
  width: 20px;
  height: 50px;
  background: #1EAFEF;
  -webkit-transform: skewX(15deg);
}

The Left side does exactly what I want it to do. However, the right side doesn't. It goes to the next line, which doesn't make any sense because I am using absolute positioning to NOT to have that issue :/

Can someone explain to me why this happens?

EDIT: Here is my expectation: Expectation

Gasim
  • 7,615
  • 14
  • 64
  • 131

3 Answers3

1

The problem is that .side have width: 20% and .text has width: 60%. However, there are some whitespaces in the HTML, which occupy additional space:

<div class="container">
  <div class="side left"></div>
  <div class="text">Hello World</div>
  <div class="side right"></div>
</div>

Therefore, the last .side doesn't fit in the remaining space, and is placed in the next line. Since its ::after pseudo-element is absolutely positioned with respect to .side (because it has position: relative), the pseudo-element is also goes to the next line.

Some ways to fix it is using float, font-size: 0, or HTML comments:

<div class="container">
  <div class="side left"></div><!--
  --><div class="text">Hello World</div><!--
  --><div class="side right"></div>
</div>

* {
  margin: 0px;
  padding: 0px;
}
.container {
  width: 100%;
  height: 50px;
  background: #1EAFEF;
}
.container > div {
  display: inline-block;
  vertical-align: top;
}
.container .text {
  line-height: 50px;
}
.container > .side {
  width: 20%;
  position: relative;
}
.container > .side.left::after {
  content: "";
  position: absolute;
  top: 0;
  right: -15px;
  width: 20px;
  height: 50px;
  background: #1EAFEF;
  -webkit-transform: skewX(15deg);
  transform: skewX(15deg);
}
.container > .side.right::after {
  content: "";
  position: absolute;
  top: 0px;
  left: 0;
  /* this needs to be -15px; but it is barely visible so I put 0 for now */
  width: 20px;
  height: 50px;
  background: #1EAFEF;
  -webkit-transform: skewX(15deg);
  transform: skewX(15deg);
}
.container > .text {
  width: 60%;
  background: white;
  text-align: center;
}
<div class="container">
  <div class="side left"></div><!--
--><div class="text">Hello World</div><!--
--><div class="side right"></div>
</div>

See How to remove the space between inline-block elements? for more solutions.

Community
  • 1
  • 1
Oriol
  • 274,082
  • 63
  • 437
  • 513
1

It's dropping to the next line because your elements add up to over 100%.

side - 20% + 20px

text - 60%

side - 20% + 20px

Total = 100% + 40px

CSS:

* {
  margin: 0px;
  padding: 0px;
}

.container {
  width: 100%;
  height: 50px;
  background: #1EAFEF;
}

.container > div {
  display: inline-block;
  vertical-align: top;
}

.container .text {
   line-height: 50px;  
}


.container > .side {
  width: 19%;
  position: relative;
}

.container > .side.left::after {
  content: "";
  position: absolute;
  display: inline-block;
  top: 0;
  right: -3%;
  width: 4%;
  height: 50px;
  background: #1EAFEF;
  -webkit-transform: skewX(15deg);
}

.container > .side.right::after {
  content: "";
  position: absolute;
  display: inline-block;
  top: 0px;
  left: -3%;
  width: 4%;
  height: 50px;
  background: #1EAFEF;
  -webkit-transform: skewX(-15deg);
}

.container > .text {
  width: 60%;
  background: white;
  text-align: center;
}

http://codepen.io/techsock/pen/dPdWgv

That will get you to 100% width.

hopkins-matt
  • 2,763
  • 2
  • 15
  • 23
  • But the positioning of before and after are absolute? Do their heights add up to the widths of the static elements? – Gasim Feb 13 '15 at 18:29
  • The heights aren't causing the problem. It's the width of 20px on the pseudo elements that seem to be causing the issue. Change the width if the side class to something like 18% to see. Also, .side.right::after should have -webkit-transform: skewX(-15deg). – hopkins-matt Feb 13 '15 at 18:32
  • Oops I meant width. Sorry – Gasim Feb 13 '15 at 18:35
1

Not sure what the exact issue is with your version, but I have a simplified one that works:

* {
  margin: 0px;
  padding: 0px;
}

.container {
  height: 50px;
  background: #1EAFEF;
}

.container > .text {
  position: relative;
  width: 60%;
  margin: 0 auto;
  background: white;
  text-align: center;
  line-height: 50px;
}

.container::before {
  content: "";
  position: absolute;
  z-index: 2;
  top: 0;
  left: calc(20% - 10px);
  width: 20px;
  height: 50px;
  background: #1EAFEF;
  -webkit-transform: skewX(15deg);
}

.container::after {
  content: "";
  position: absolute;
  top: 0;
  right: calc(20% - 10px);
  width: 20px;
  height: 50px;
  background: #1EAFEF;
  -webkit-transform: skewX(15deg);
}
<div class="container">
  <div class="text">Hello World</div>
</div>
janfoeh
  • 10,243
  • 2
  • 31
  • 56
  • I will be using .text::after and .text::before for something else, so I don't want to use it for that. – Gasim Feb 13 '15 at 18:30
  • @Gasim here's an alternative version that hooks the pseudo elements to .container instead. Be aware that it's IE9+ only though due to the use of `calc`. – janfoeh Feb 13 '15 at 18:36