13

I'd like to use the CSS border attribute to make a fine 1px grid between span elements, like so.

     |    
  1  |  2  
-----|-----
  3  |  4  
     |    

This is what I currently have. It doesn't quite work obviously.

<html>
<head>
<style>
  div {
    width: 204px;
  }
  span {
    display: inline-block;
    height: 100px;
    width: 100px;
    border: 1px solid #ccc;
    border-left-width: 0;
    border-top-width: 0;
  }
</style>
</head>
<body>
<div><span>1</span><span>2</span><span>3</span><span>4</span></div>
</body>
</html>

When the div is set to 306px and the elements reflow, the solution should adapt dynamically.

     |     |
  1  |  2  |  3
-----|-----|-----
  4  |
     |

Preferably CSS only, or pure Javascript. Older browsers like IE7 can be ignored.

5 Answers5

23

I came up with this approach, which I think works pretty well with minimal CSS and hacks: https://codepen.io/eriklharper/pen/JMKMqa

    .border {
      background-color: gray;
    }
    .grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(auto, auto));
      grid-gap: 1px;
    }
    .grid > div {
      background-color: white;
      padding: 10px;
    }
    <div class="border">
      <div class="grid">
        <div>Item 1</div>
        <div>Item 2</div>
        <div>Item 3</div>
        <div>Item 4</div>
      </div>
    </div>

It introduces an extra wrapping element around the whole grid (which isn't perfect either) but I've found this to be a worthwhile compromise, despite. The lack of ability to simply style the grid-gaps directly is a shortcoming with CSS Grid that should be addressed with the spec.

Dai
  • 141,631
  • 28
  • 261
  • 374
eriklharper
  • 2,882
  • 5
  • 25
  • 28
  • 11
    Your example contains selectors that are not actually CSS: `& > div`. It would be nice to mention that so you don't confuse newbies. (Or just re-write it in pure CSS.) – J.D. Sandifer May 07 '18 at 18:19
  • 8
    Why not use `background-color: gray;` on the grid container itself? You wouldn't need an extra wrapping element or am I wrong? – tamarin Jun 19 '20 at 22:21
3

1. HTML+CSS solution

HTML:

<div>
    <i></i>
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
    <i></i>
</div>​

CSS:

div {
    position: relative;
    width: 202px;  /* or 303px (or 100px * n + n) */
    font-size: 0;
}

span {
    display: inline-block;
    height: 100px;
    width: 100px;
    border: 1px solid #ccc;
    border-left-width: 0;
    border-top-width: 0;
    font-size: 12px;
}

i {
    position: absolute;
    background: #fff;
    height: 1px;
    bottom: 0;
    left: 0;
    width: inherit;
}

​i:first-child {
    height: auto;
    width: 1px;
    top: 0;
    left: auto;
    right: 0;
}​

DEMO: http://jsfiddle.net/HTgKJ/


2. HTML+CSS+JavaScript solution

HTML+CSS:

<!-- See approach 1. -->

JavaScript:

var block = document.querySelectorAll(".block");
for (var i = 0; i < block.length; i++) {
    var spanWidth = block[i].querySelector("span").clientWidth,
        n = Math.floor(block[i].clientWidth / spanWidth);
    
    block[i].querySelector("i:first-child").style.left =
        (n * spanWidth + (n - 1)) + "px";
}​

DEMO: http://jsfiddle.net/HTgKJ/1/

Community
  • 1
  • 1
VisioN
  • 143,310
  • 32
  • 282
  • 281
  • This works, but rather than covering the lines up, I've rather not have them in the first place. The former can cause some alignment problems when zooming. I'm using a different solution, which is a bit like the other answer, but in pure JavaScript. –  Dec 12 '12 at 03:06
1

I'm using this solution, which automatically sets the border.

http://jsfiddle.net/aLz2T/3/

HTML

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

CSS

div {
    width: 204px; /* adjust to get less/more columns */
}

span {
    display: inline-block;
    height: 100px;
    width: 100px;
    border: 1px solid #ccc;
    border-left-width: 0;
    border-top-width: 0;
}​

JavaScript

var a = document.querySelector('div');

// columns
var b = parseInt(a.offsetWidth / (100 + 2), 10);

for(var c, d = document.querySelectorAll('span'), e = d.length, i = 0; c = d[i]; i++) {
    // column
    c.style.borderRightWidth = ((i + 1) % b) != 0 ? "1px" : "0";
    // row
    c.style.borderBottomWidth = parseInt(i / b, 10) * b < e - b ? "1px" : "0";
}​
1
  1. Make the background color of the containing element the color you want for the border.
  2. Make the background color of the elements within the grid the color you really want as the background.
  3. Add a gap of 1, or the desired border thickness.
.grid {
  display: grid;
  background-color: orange;
  gap : 1;  
}

.grid > * {
  background-color: blue;
}

how it looks

Code Whisperer
  • 22,959
  • 20
  • 67
  • 85
-2

Here you can find my solution with jQuery. http://jsfiddle.net/UZJmd/7/

You just jave to put how many spans you want and then define the number of columns you want. Everything else is defined dinamically.

​1- var spanWidth = parseInt($("span").css("width")); 
2- var spanSize = $("span").size();
3- var nColumns = 2;
4- var nLines = Math.floor(spanSize/nColumns+0.5);
5- 
6- $(function() {
7-     $("div").css({"width": (spanWidth*nColumns + 1*(nColumns-1))+"px"});
8-     for(var i = 0; i <= spanSize; i++) {
10-         if((i+1)%nColumns == 0) {
11-             $('span').eq(i).css({"border-right": 0});
13-         }
14-         if(Math.floor(i/nColumns) >= nLines-1) {
15-             $('span').eq(i).css({"border-bottom": 0});
16-         }
17-     }
18- });

In line 3 we define the number of columns we want. In line 10 we check if it's the last span of the line and we set the right border to 0. In line 14 we check if we are in the last line and then set the bottom border to 0.

Dim13i
  • 1,961
  • 1
  • 17
  • 20
  • I don't use jQuery, but my solution is similar, just that it gets the columns dynamically. –  Dec 12 '12 at 03:07
  • @pdknsk Yes it's quite similar, the difference is that in my solution we choose the n° of columns and in your solution we define the size of the `
    `. But you use only Javascript which is what the user asked for ;)
    – Dim13i Dec 12 '12 at 12:03
  • 2
    jQuery is overkill and bloat here. – OverCoder Jan 08 '19 at 15:27