Drawing Diagonal Lines with CSS

CSS allows you to specify so many bizarre graphical properties, that I couldn't believe it doesn't support drawing simple lines. Well, it doesn't. And googling for how to draw a diagonal line was not effective. The closest result I got was how to draw a trapezoid.

So how to draw lines? The first idea that crossed my mind was stretching images of diagonal lines (which this site suggests as well, after suggesting to implement Breshenham 🙂 ). However, all resulting lines  have popping pixels, missing pixels, and a general unevenness.

So, I present a new way. It's purely in CSS, involves little code, draws very quickly and can be used for almost any diagonal line possible.

Of course it has its problems as well, and I will discuss them later.

Drawing Diagonal Lines

Diagonals Example

Demonstration of my diagonals technique

Lines can be drawn by improving on the trapezoid technique, and placing a "white triangle" (a trapezoid without a width) with a slight offset on top a "solid triangle" to erase its body.

Here's how the HTML and CSS look (make sure you understand how the trapezoid is done before you continue reading, so you'll understand the rest):

<style type="text/css">
  .line {
    position:absolute; /* doesn't have to be absolute */
    z-index: -1;         /* places the line behind other elements */
  }

  .line div {
    position:absolute;
    left: 0px; top: 0px;
    border-left-color: transparent;
    border-style: solid;
  }
</style>
<!-- a line from A to B -->
<div class="line" style="left:50px; top:40px; /* point A */">
<div style="
    border-width: 0px 0px 150px 100px;        /* point B (minus A) */
    border-bottom-color: red;                 /* line color */
  "></div>
<div style="
    left: 2px;                                /* line width */
    border-width: 0px 0px 150px 100px;        /* point B (minus A) */
    border-bottom-color: white;               /* background color */
  "></div>
</div>

Explanation

The outer div contains the line. Position it as you wish (I chose absolute positioning and this is probably what you want too. left and top can be used to set the coords for the beginning of the line).
Putting it in the background (using a negative z-index) is very important, or the erasing-triangle will erase your content as well.

Inside it, are two inner divs. The first one is the solid-triangle. Its border-width determines the end-point of the line (meaning: its angle and length). Its border-bottom-color is the color of the line.

The second div is the eraser-triangle. Its border-width must match the first div's, unless you want your line to have a varying width (practically rendering it a triangle). The left property specifies the width of the line (by actually deciding the offset of the erasing-triangle). Now, this is not so simple: It specifies the horizontal width. So as the line leans more and more to the right, the line will seem thinner. It is important to increase left proportionally to maintain desired line-width. Another important issue is the erasing-color (that is, the border-bottom-color). Its color should match that of the background.

Suggestions

This only demonstrates a rising line, but can be as easily used for a falling line by using right borders and a negative left for the erasing triangle.

To save the trouble of calculations, a simple JavaScript function can be used to draw these lines.

Limitations

Nothing is perfect, and this technique is not even close to being so.

  • Background must be solid - I can't think of a way to allow the lines on top of an image background.
  • Lines cannot intersect - This is basically the same as the previous, but worth mentioning
  • Cannot draw horizontal and vertical lines. They're easy to draw, but it's less pretty (for the programmer).
  • Must distinguish between rising and falling lines - again, less pretty.
  • Lines have to be declared in a specific order: Lower lines should appear later in the HTML (unless you specify their z-index manually)

Conclusion (just for fun)

I presented here a novel method for drawing lines using CSS. It has certain strengths and weaknesses. In general, I think it is very useful.

Enjoy!

Diagonals Example 2

Another demonstration

Tags: , , ,

Categorised in:

12 Comments

  • The unevenness of my technique is easily fixed, and the image streching approach does not suffer from any of the limitations you have :p

    Border slants are best used to draw flat polygons than lines.

  • erezsh says:

    You are incorrect. It suffers two of them.
    True, they are better for polygons, as future posts might prove.

  • I'm afraid you missed something about my approach because it has none of the limitations of yours. For instance by strecthing tranparent diagonals:

    * the direction of the lines has not impact on the markup or css
    * horizontals and verticals are supported
    * interesection is not a problem at all
    * lines have a transparent background and thus can be draw with any z-index you want and don't require a solid color background or any specific order for the markupu

  • Nick says:

    A more flexible approach for drawing arbitrary lines in recent browsers is to use rotated HTML div elements. Recent versions of Firefox, Chrome and Safari support the 2D transformations module which allows elements to be rotated. In IE, the filter property provides similar functionality. For example, in Firefox or Chrome we can use

    line.style.MozTransform = line.style.WebkitTransform = "rotate(" + angle + "rad)";

    or in IE 5.5+

    line.style.filter = "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=" + nCos + ", M12=" + -1*nSin + ", M21=" + nSin + ", M22=" + nCos + ")";

  • Ed says:

    This is great! Thanks Mathieu 'p01' Henri! Exactly what I was looking for.

  • Anonymous says:

    can you use position fixed instead?

  • It's in point of fact a nice and useful piece of info. I'm happy that you simply shared this useful info with us. Please keep us up to date like this. Thanks for sharing.

  • Chris says:

    nice, i am looking for something like this.
    is it possible to add the start/end positions automaticly
    from 2 container ?
    i wont to connect Pictures but when i move one to a different position, the lines ar no longer correct in position.
    is there any solution for this ? (maybe only html/css if possible)

    thx
    Chris

    • erezsh says:

      This is an old post, from before css3. I suggest you use css3's rotate to achieve this.

Leave a Reply

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