137

Say I have two divs next to each other (take https://chrome.google.com/webstore/category/home as reference) with a border.

Is there a way (preferably a CSS trick) to prevent my divs from appearing like having a double border? Have a look at this image to better understand what I mean:

"Double" border

You can see that where the two divs meet, it appears like they have a double border.

ЯegDwight
  • 24,821
  • 10
  • 45
  • 52
john smith
  • 1,963
  • 2
  • 17
  • 16

19 Answers19

111

If we're talking about elements that cannot be guaranteed to appear in any particular order (maybe 3 elements in one row, followed by a row with 2 elements, etc.), you want something that can be placed on every element in the collection. This solution should cover that:

.collection {
    /* these styles are optional here, you might not need/want them */
    margin-top: -1px;
    margin-left: -1px;
}

.collection .child {
    outline: 1px solid; /* use instead of border */
    margin-top: 1px;
    margin-left: 1px;
}

Note that outline doesn't work in older browsers (IE7 and earlier).

Alternately, you can stick with the borders and use negative margins:

.collection .child {
    margin-top: -1px;
    margin-left: -1px;
}
Zachary Dahan
  • 1,419
  • 16
  • 26
cimmanon
  • 67,211
  • 17
  • 165
  • 171
29

#divNumberOne { border-right: 0; }

Andy
  • 14,427
  • 3
  • 52
  • 76
  • 21
    This is the only real way of doing it that doesn't mess other stuff up. If you need to do multiple elements, hell, say 100 divs, you could do `div { border-right: none; } div:last-child { border-right: 1px solid black; }` which would give you the intended effect – Andy Oct 02 '12 at 14:24
  • 1
    yea, it can always be done that way, but i was wondering if there was a pure-css way of doing it, without having to use more than one class (i will have more rows and columns) – john smith Oct 02 '12 at 14:27
  • 3
    This is pure css, I used a pseudo class (last child) so I haven't modified the html in anyway, there are many pseudo classes and I would say go down this route as I don't think there is an alternative – Andy Oct 02 '12 at 14:28
  • Look into Nth Child you can do it this way using odd and even or depending on your layout you can calculate it the way you want. – MaxwellLynn Feb 02 '14 at 17:50
  • 1
    Why was this accepted as the correct answer? I really don't think this is what he was looking for. This is certainly not a scalable solution either. – Kevin Behan Nov 12 '16 at 01:22
24

HTML:

<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>

​CSS:

div {
    border: 1px solid #000;
    float: left;
}

div:nth-child(n+2) {
    margin-left: -1px;
}

Demo

Include ie9.js for IE8 support (it's very useful for all CSS selectors/pseudo-elements).

Ry-
  • 218,210
  • 55
  • 464
  • 476
Giona
  • 20,734
  • 4
  • 56
  • 68
  • if you have more than one row first div in second row have no left border and with this trick divs alignment go to left for 1px – Afshin Oct 02 '12 at 15:08
  • Wasn't there no more complicated version? What about elements with a larger `right-margin`? – feeela Oct 02 '12 at 15:11
  • @afshin if i don't see his layout how can i give a specific answer? – Giona Oct 02 '12 at 15:11
  • @feeela i think it's pretty basic. Anyway, `right-margin` doesn't affect `left-margin`: http://jsfiddle.net/gionaf/D6tHK/1/ – Giona Oct 02 '12 at 15:13
  • 1
    This solves the lateral double borders, but not the vertical ; borders in the bottom/top are still doubled. Any hints for those ? – delphirules Oct 23 '15 at 12:40
23

Another solution one might consider is using the CSS Adjacent sibling selector.

The CSS

div {
    border: 1px solid black;
}

div + div {
    border-left: 0;
}

jsFiddle

Stephan
  • 360
  • 3
  • 9
18

I'm late to the show but try using the outline property, like so:

.item {
  outline: 1px solid black;
}

Outlines in CSS do not occupy physical space and will therefore overlap to prevent a double border.

Michael Giovanni Pumo
  • 14,338
  • 18
  • 91
  • 140
  • 1
    also works, when a row breaks into more rows on smaller screens - all the other answers don`t work when your divs could break into new rows. you then have at least one div with a side without a border. thx for sharing - upvoted – DigitalJedi May 03 '20 at 12:24
  • Much better to have a solution than a hack. Thank you. – forrest Sep 23 '20 at 20:49
  • 6
    didn't work for me. Still got the double border and a possible bug. you could see the outline above my scrollbar, which does not happen with border. – Jesper Jul 13 '22 at 07:49
7

You can use odd selector to achieve this

.child{
   width:50%;
   float:left;
   box-sizing:border-box;
   text-align:center;
   padding:10px;
   border:1px solid black;
   border-bottom:none;
}
.child:nth-child(odd){
   border-right:none;
}
.child:nth-last-child(2),
.child:nth-last-child(2) ~ .child{
   border-bottom:1px solid black
}
<div>
    <div class="child" >1</div>
    <div class="child" >2</div>
    <div class="child" >3</div>
    <div class="child" >4</div>
    <div class="child" >5</div>
    <div class="child" >6</div>
    <div class="child" >7</div>
    <div class="child" >8</div>
</div>

enter image description here

yasarui
  • 6,209
  • 8
  • 41
  • 75
  • wouldn't it be better to do nth-child(even){border-left:none;} ? That way there could be an odd number of columns... – pixelearth Nov 18 '18 at 21:46
5

If the divs all have the same class name:

div.things {
    border: 1px solid black;
    border-left: none;
}

div.things:first-child {
    border-right: 1px solid black;
}

There's a JSFiddle demo here.

Roddy of the Frozen Peas
  • 14,380
  • 9
  • 49
  • 99
2

Add the following CSS to the div on the right:

position: relative;
left: -1px; /* your border-width times -1 */

Or just remove one of the borders.

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
2

Using Flexbox it was necessary to add a second child container to properly get the outlines to overlap one another...

<div class="grid__container">
    <div class="grid__item">
        <div class="grid__item-outline">
              <!-- content -->
        </div>
    </div>
</div>

SCSS

.grid__container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    margin: 0 1px 0 0; // margin-right 1px to give the correct width to the container
}

.grid__item {
    flex: 0 1 25%; // grid of 4
    margin: 0 0 1px; // margin-bottom to prevent double lines
}

.grid__item-outline {
    margin: 0 0 0 1px; // margin-left to prevent double lines
    outline: 1px solid #dedede;
}
ness-EE
  • 1,334
  • 13
  • 19
2

If you also need to change border colors on interaction (eg. swatch selector in a form), I found out a nice trick to do it, using a combination of negative margins, padding adjustment and transform translate. Check it out:

.parent{
  display: flex;
  width: 100%;
  max-width: 375px;
  margin-left:1px;
}

.child {
  margin-left: -1px;/* hide double borders behind their siblings */ 
  flex: 1 0 auto;
}

.child input {
  display:none
}

.child label {
  display:block;
  border: 1px solid #eaeaea;
  min-height: 45px;
  line-height: 45px;
  cursor: pointer;
  padding: 0 10px; /* will be changed when input is checked */
  font-size: 15px;
  text-align: center;
}

.child input:checked+label {
  border: 1px solid red;
  transform: translateX(-1px);
  padding-left: 11px;
  padding-right: 9px;
  background-color: #fafafa;
}
<div class="parent">
  <div class="child">
    <input id="swatch-1" type="radio" value="1" name="option" checked="true">
    <label for="swatch-1">Element 1</label>
   </div>
   <div class="child">
    <input id="swatch-2" type="radio" value="2" name="option">
    <label for="swatch-2">Element 2</label>
   </div>
   <div class="child">
    <input id="swatch-3" type="radio" value="3" name="option">
    <label for="swatch-3">Element 3</label>
   </div>
 </div>
Max
  • 169
  • 2
  • 11
1

I just use

border-collapse: collapse;

in the parent element

JayCee
  • 19
  • 1
1

My use case was for boxes in a single row where I knew what the last element would be.

.boxes {
  border: solid 1px black  // this could be whatever border you need
  border-right: none;
}

.furthest-right-box {
  border-right: solid 1px black !important;
}
Sam Henderson
  • 479
  • 5
  • 7
1

To add to a 9 year old question, another clean and responsive way to achieve this is to:

  • Add a border-left and border-top to the parent
  • Add border-right and border-bottom to each of the children
Jasper
  • 560
  • 4
  • 15
0
  <div class="one"></div>
  <div class="two"></div>
  <div class="two"></div>
  <div class="two"></div>
  <div class="two"></div>

CSS:

  .one{
    width:100px;
    height:100px;
    border:thin red solid;
    float:left;
  }
.two{
    width:100px;
    height:100px;
    border-style: solid solid solid none;

    border-color:red;
    border-width:1px;
    float:left;
}

jsFiddle

Afshin
  • 4,197
  • 3
  • 25
  • 34
0

I know this is a late reaction, but I just wanted to drop my 2 cents worth, since my way of doing it is not in here.

You see, I really don't like playing with margins, especially negative margins. Every browser seems to handle these just that tad bit different and margins are easily influenced by a lot of situations.

My way of making sure I have a nice table with divs, is creating a good html structure first, then apply the css.

Example of how I do it:

 <div class="tableWrap">
   <div class="tableRow tableHeaders">
     <div class="tableCell first">header1</div>
     <div class="tableCell">header2</div>
     <div class="tableCell">header3</div>
     <div class="tableCell last">header4</div>
   </div>
   <div class="tableRow">
     <div class="tableCell first">stuff</div>
     <div class="tableCell">stuff</div>
     <div class="tableCell">stuff</div>
     <div class="tableCell last">stuff</div>
   </div>
</div>

Now, for the css, I simply use the rows structure to make sure the borders are only where they need to be, causing no margins;

.tableWrap {
  display: table;
  }

.tableRow {
  display: table-row;
  }

.tableWrap .tableRow:first-child .tableCell {
  border-top: 1px solid #777777;
  }

.tableCell {
  display: table-cell;
  border: 1px solid #777777;
  border-left: 0;
  border-top: 0;
  padding: 5px;
  }

.tableRow .tableCell:first-child {
  border-left: 1px solid #777777;
  }

Et voila, a perfect table. Now, obviously this would cause your DIVs to have 1px differences in widths (specifically the first one), but for me, that has never created any issue of any kind. If it does in your situation, I guess you'd be more dependant on margins then.

NoobishPro
  • 2,539
  • 1
  • 12
  • 23
0

I was able to achieve it using this code:

td.highlight {
    outline: 1px solid yellow !important;
    box-shadow: inset 0px 0px 0px 3px yellow;
    border-bottom: 1px solid transparent !important;
}
estinamir
  • 435
  • 5
  • 11
0

A very old question, but it was the first google result, so for anyone that comes across this and doesn't want to have media queries to re-add the border to the right/left of the element on mobile etc.

The solution I use is:

.element {
    border: 1px solid black;
    box-shadow: 0 0 0 1px black;
}

This works because you'll see a 2px border around the element made of the border and the shadow. However, where the elements meet, the shadow overlaps which keeps it 2px wide;

abnoas
  • 1
-1

What about giving a margin:1px; around your div.

<html>
<style>
.brd{width:100px;height:100px;background:#c0c0c0;border:1px solid red;float:left;margin:1px;}
</style>
<body>
    <div class="brd"></div>
    <div class="brd"></div>
    <div class="brd"></div>
</body>
</html>

DEMO

defau1t
  • 10,593
  • 2
  • 35
  • 47
-3

I prefer to use another div behind them as background and delete all the borders. You need just to calculate the size of the background div and the position of the foreground divs.

well7m
  • 21
  • 3
  • I do think my solution is the best although the critics. It's the same principe as drawing a 1px table : – well7m Oct 03 '12 at 07:09