Filling a Square with Diagonal Lines in CSS

Facebooktwittergoogle_plustumblrmailFacebooktwittergoogle_plustumblrmail
a square filled with diagonal lines in css

A square filled with diagonal lines in css

I’ve been playing with CSS this week. I spent a few days working through the Daily CSS Image challenges. Then, yesterday, I had an idea to try to create a crosshatched image using CSS. The first thing I wanted to do was fill a square with diagonal lines. This might sound like an easy task, but it ended up being an adventure into madness. Filling a square with diagonal lines in CSS is not as easy as it sounds.

Finding a pattern for diagonal lines in css

a box with four diagonal lines added manually

A box with four diagonal lines added manually

I’m working in CodePen and started out by adding each line one at a time. After adding four lines, I noticed a pattern:

.line0 {
    top: -2px;
    left: 5px;
    height: 15px;
}

.line1 {
    top: -4px;
    left: 10px;
    height: 30px;
}

.line2 {
    top: -6px;
    left: 15px;
    height: 45px;
}

.line3 {
    top: -8px;
    left: 20px;
    height: 60px;
}

Each line is 15px longer than the previous line, pushed up 2px, and pushed left 5px. I decided this was a good time to switch on Sass. With Sass I can build a for loop to adjust these properties automatically.

Building a for loop

Diagonal lines added with too many iterations

Diagonal lines added with too many iterations.

The first thing I need to do is figure out how many iterations my for loop will have. The formula for determining the length of a diagonal of a square is l*\sqrt{2} where l = length of a side. I’m shifting my lines left 5px, so, given this, my thought is that my iterations should be (l*\sqrt{2})/5px. This, however, did not work. I ended up with too many iterations, as seen in the image to the left. (Note that at this point the length of the lines has not been adjusted.)

This was a problem that perplexed my for a long time. Initially, I just did some guessing and hard coded in the number of iterations based on what looked best. Later, I realized that when I apply the top offset, it actually pushes the line a little more to the left. Through trial and error I found that the number of lines that looked best on a 300px x 300px square was around 57 (55, 56, 57 all looked find). When I divide l*\sqrt{2} by 57, I get 7.4432. I decided this was close enough to 7.5 to just call it roughly 7.5px. I plugged that into my iterations formula and viola! it actually worked. The final formula is (l*\sqrt(2))/7.5px.

Now that I know how many times I am iterating through my loop, I can go about the business of building the loop. I’m still not accounting for the fact that my lines need to get smaller (and shift, more on that later) once I get to the halfway point. So, at this point, my loop looks like this:

$xoff: -2px;
$yoff: 5px;
$growth: 15px;
$l: 300px;
$its: floor(($l*sqrt(2)/7.5px)));
$top: 0px;
$bottom: 0px;
$height: 0px;
$left: 0px;
$right: 0px;

@for $i from 0 through $its {
    .line#{$i} { 
        $height: $height + $growth;
        $top: $top + $xoff;
        $left: $left + $yoff;
        top: $top;
        left: $left;
        height: $height;
    }
}

// This class applies to all lines
.lineA {
    width: 1px; 
    background-color: gray;
    position: absolute;
    transform: rotate(45deg);
}

Now I am able to fill the square with lines, but the lines are not yet forming the shape of the square. I need to make my lines get smaller once I reach the half-way point. A task that is more challenging than it may seem.

Filling the right half of the square

First attempt to fill second half of a square with diagonal lines in css.

First attempt to fill second half of a square with diagonal lines in css.

The loop I have built so far does a fine job of filling the left half of the square, but the lines are too long and run over once it passes the halfway point.  My first thought was just to negate everything. So instead of adding 15px to the height, I was subtracting 15px; instead of offset the top by -2px, I was offsetting it by 2px; etc. It sounds reasonable, but, in practice, it did not work. The result is what you see to the left.

I figured the problem was that I was still using the left and top properties. For the second half of the square, it makes more sense to use the right and bottom properties. This meant adding an @if @else to my loop.

Filling a square with diagonal lines, adding in the second half causes an interesting issue

Filling a square with diagonal lines, adding in the second half causes an interesting issue

Now, instead of adding my offsets, I am subtracting them. It worked out better, but i still had an odd problem. The two halves were not meeting up (see image to the right). I was able to fix this by adjusting the bottom and right properly for each line by a fixed amount.

After creating a few different square sizes using what I have at this point, I noticed that the bottom offset is roughly l/2 and the right offset is roughly l/3. Unfortunately, it’s not exactly half and third, so it requires an additional offset.

What I came up with to compensate for this is very hacky and not at all what I would like to do, but it works for now. I have $roffset and $boffset variables that need to be manually adjusted at different sizes. The final code is below.

@import "compass";

$xoff: -2px;
$yoff: 5px;
$growth: 15px;
$l: 600px;
$boff: 55px; // Manually adjusted
$roff: -17px; // Manually adjusted
$its: floor(($l*sqrt(2)/7.5px));
$lines: 56;
$half: $l / 2;
$third: $l / 3;
$top: 0px;
$bottom: 0px;
$height: 0px;
$left: 0px;
$right: 0px;

.box {
    height: $l;
     width: $l;
     //background: pink;
     margin: 100px auto;
     position: relative;
}

.lineA {
     width: 1px; 
     background-color: gray;
     position: absolute;
     transform: rotate(45deg);
}

@for $i from 0 through $its {
     .lineA#{$i} { 
        @if($i < ($its/2)) {
          $height: $height + $growth;
          $top: $top + $xoff;
          $left: $left + $yoff;
           top: $top;
           left: $left;
     } 
     @else {
           $height: $height - $growth; 
           $right: ($right - $yoff);
           $bottom: ($bottom - $xoff);
           bottom: -$third + $boff + $bottom;
           right: $half - $roff + $right;
     }
        height: $height;
     }
}

This, however, is not a perfect solution. The lines actually drift a bit. If you turn on a background on the containing div, things are not quite right. For now, though, it is in the realm of good enough. At some point, I need to spend some time seeing if I can come up with better math.

Final result of adding diagonal lines to a square using CSS.

Final result of adding diagonal lines to a square using CSS.

If you’d like to play around with this, feel free to form the CodePen here: Filling a Square with Diagonal Lines in CSS

Leave a Reply

Your email address will not be published. Required fields are marked *