Using flex and flex-wrap with borders [duplicate] - css

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:
You can see that where the two divs meet, it appears like they have a double border.

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;
}

#divNumberOne { border-right: 0; }

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).

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

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.

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>

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.

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.

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;
}

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>

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;
}

<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
​

I just use
border-collapse: collapse;
in the parent element

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.

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;
}

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;

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

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

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.

Related

Top menu without flex, without calc(...) for legacy support

I'm trying to do a top menu with a 1px border. How to have the #mid div use the full middle width (so that the bottom-border goes close to #right) ?
I'm looking for a solution without flex, without width: calc(...), because it's not supported on some devices I did tests on (legacy support needed).
* { margin:0; padding: 0; }
.left { float:left; width: 155px; height: 60px; border-right: 1px solid #dedede; border-bottom: 1px solid #dedede; }
.mid { float:left; height: 60px; border-bottom: 1px solid #dedede; display:inline-block; }
.right { float: right; width: 40%; height: 60px; border-left: 1px solid #dedede; border-bottom: 1px solid #dedede; }
<div>
<div class="left">aa</div>
<div class="mid">aa</div>
<div class="right">bb</div>
</div>
the display:table layout properties can help you to start with : (=>IE8)
table shrinks/expands to hold content. that's why .mid will use as much space avalaible squizing others table-cell elements being less than the 100% width set in CSS. Mind that If content is wider than the tabled container, it will grow over the 100% width.
* { margin:0; padding: 0;box-sizing:border-box; }
.tb {
display:table;
width:100%;
border:solid 1px;
}
.tb > div {
display:table-cell;
border:inherit ;
}
.mid { width:100%; }
<div class="tb">
<div class="left">aa</div>
<div class="mid">aa</div>
<div class="right">bb</div>
</div>
<hr/>
<div class="tb">
<div class="left">longer</div>
<div class="mid">aa</div>
<div class="right">longer</div>
</div>
or float properties and block formating context :(to include IE6 add zoom:1; aside overflow)
.left and .right are to float and be first in the flow.
middle will come in between, BFC will avoid .mid to lay under floating elements.
div div {
border:solid 1px ;
overflow:hidden;/* modify BFC */
}
.left {
float:left;
}
.right {
float:right
}
<div >
<div class="left">aa</div>
<div class="right">bb</div>
<div class="mid">mid</div>
</div>
<hr/><div >
<div class="left">longer</div>
<div class="right">longer</div>
<div class="mid">mid</div>
</div>

ignore padding div inside div - CSS

I have a div inside another div and I want this second div to ignore the padding, the second div to have full width and no margin bottom. How can I make it work?
#first {
padding: 10px;
border: 1px solid #000;
}
#second {
background-color: red;
color: #fff;
}
<div id="first">
first div with 10px padding
<div id="second">
no padding
</div>
</div>
Inner element can compensate parents padding by using negative margin.
#second {
background-color:red;
color:#fff;
margin: -10px;
}
http://jsfiddle.net/n5yx8903/1/
wrap text in p or span tag
<div id="first">
<p>first div with 10px padding</p>
<div id="second">
no padding
</div>
</div>
set margin for element wrapping text, this will be the cleanest solution.
https://jsfiddle.net/n5yx8903/
Set margin-left and margin-right to -10px.
#second{
background-color:red;
color:#fff;
padding: 0;
margin-left: -10px;
margin-right: -10px;
}
Here is Fiddle.
Well CSS is not intended to do this,
you may do this with negative margin, but as you see in the fiddle, it will then overflow:
http://jsfiddle.net/n5yx8903/6/
#first{
padding:10px;
border:1px solid #000;
}
#second{
background-color:red;
color:#0ff;
margin:-10px;
}
Maybe this SO answer will help you understand this problem better:Why does CSS not support negative padding?
That is not doable in CSS. I think when that happens there are two options you can do.
Use negative margin to compensate the padding
Restructure the HTML
I would choose the latter one whenever possible and use negative margin as a fallback option.
#container {
border: 1px solid #000;
}
#first {
padding: 10px;
}
#second {
background-color: red;
color: #fff;
}
<div id="container">
<div id="first">
first div with 10px padding
</div>
<div id="second">
no padding
</div>
</div>
You can just put "first div with 10px padding" text into another div:
#first {
border: 1px solid #000;
}
#second {
background-color: red;
color: #fff;
}
#inner {
padding: 10px;
}
<div id="first">
<div id="inner">
first div with 10px padding
</div>
<div id="second">
no padding
</div>
</div>
You can just switch the divs
#first{
border:1px solid #000;
}
#second{
background-color:red;
color:#fff;
padding:0px 10px;
}
<div id="first">
<div id="second">
first div with 10px padding
</div>
no padding
</div>

Positioning stacked divs at the bottom of a container

I'm building a staked bar graph in PHP. I need it to look like this:
Currently I am able to stack-up the gray and red values, but they are at the top of the .graph container. How do I align them at the bottom? I tried vertical-align: bottom but it did not really work.
<div class="graph">
<div class="bar">
<div class="views" style="height:'.$showViews.'px"></div>
<div class="actions" style="height:'.$showActions.'px"></div>
</div>
</div>
and CSS
.graph {
width: 200px;
height: 32px;
border-top: 1px solid #f5f5f5;
border-bottom: 1px solid #ccc;
background-color: #f5f5f5;
}
.graph .bar {
width: 10px;
float: left;
margin: 0 1px;
height:30
}
.graph .bar .views {
background-color: #ccc
}
.graph .bar .actions {
background-color: red
}
Here's my code on JSFIDDLE.
Thanks.
position:absolute will make your life easier!
Here's a fiddle:
http://jsfiddle.net/RZ8ye/1/
Basically, we're using position:absolute to stack the elements on top of one another. By giving the parent positioning (in our case, "relative"), we position the stacked elements relative to that. We set bottom, left, and right and then define the height with an inline style (percentage based, based on the parent)
just added position:relative value in CSS.
here is the modified code.
.graph .bar .views
{
background-color: #ccc;
height:10px; /*height can be added dynamically*/
position:relative;
}
.graph .bar .actions
{
background-color: red;
position:relative;
height:20px;
}
HTML looks like same as posted .
<div class="graph">
<div class="bar">
<div class="views" style="height:'.$showViews.'px"></div>
<div class="actions" style="height:'.$showActions.'px"></div>
</div>
<div class="bar">
<div class="views" style="height:'.$showViews.'px"></div>
<div class="actions" style="height:'.$showActions.'px"></div>
</div>
</div>
Here is the Demo. http://jsfiddle.net/HHnRQ/1/

Width not expanding?

I'm working on a map project and for some reason my tooltip's text width will continue to expand as wide as I want until I add a space to my text. If I add a space, it breaks to the next line; what is going on and how do I fix this? I'd like the text on one line without specifying a width so it can automatically set the width, how can I fix this?
In the example below, look at text "Baseball Fields" in the paragraph tag. If it reads "BaseballFields" it will stay on one line. But as soon as I add the space, it will line break.
<div style="width: 750px; height: 1221px; border: 0; padding: 0; margin-top: 10px; display: block; position:relative; background: url('http://www.thefirstacademy.org/filerequest/9701.jpg') no-repeat left top;">
<style type="text/css">
.triangle {
position:absolute;
bottom:-5px;
left:40%;
height:0;
width:0;
border-left:5px solid transparent;
border-right:5px solid transparent;
border-top:5px solid white;
}
.tooltip {
color:#ef4c4c;
background:#ffffff;
padding:17 10;
display:block;
position:absolute;
border-radius:5px;
font:.8em 'MuseoSans-500','Museo Sans';
top:-40px;
box-shadow:0px 3px 3px #000;
border:1px solid #000;
}
</style>
<div class="marker" style="position:absolute;cursor:pointer;left:450px;top:75px;" id="baseball">
<img src="http://www.thefirstacademy.org/filerequest/9702.png" alt="Location Marker" />
<div class="tooltip" >
<div class="triangle"></div>
<p style="padding:0;margin:0;line-height:0;display:block;">Baseball Fields</p>
</div>
</div>
</div>
Just a heads up: in addition to white-space: nowrap; it can be helpful to include display: inline-block; for browser compatibility purposes

Preventing "double" borders in CSS

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:
You can see that where the two divs meet, it appears like they have a double border.
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;
}
#divNumberOne { border-right: 0; }
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).
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
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.
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>
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.
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.
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;
}
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>
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;
}
<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
​
I just use
border-collapse: collapse;
in the parent element
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.
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;
}
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;
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
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
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.

Resources