If you search online for how to draw a triangular shape in CSS, chances are the top results will still recommend the border method, as described in this 15-plus-year-old CSS-Tricks article:
The idea is a box with zero width and height. The actual width and height of the arrow is determined by the width of the border. In an up arrow, for example, the bottom border is colored while the left and right are transparent, which forms the triangle.
.arrow-up {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid black;
}
I still stand by most of what I wrote in my original article: this method is a hacky solution from a time when there were no other CSS options. It works, but it isn't how borders were meant to be used.
So what made me "change my mind" and say that it might be okay to use this method after all?
The answer is: logical properties.
Logical properties define direction-relative equivalentes to classic physical properties. Instead of thinking in terms of left/right or top/bottom, we think in terms of inline/block and start/end.
This is especially useful when creating layouts that must support multiple writing modes and reading directions. Not every language follows the familiar left-to-right, top-to-bottom flow of English. For example, Arabic is written right-to-left, while Japanese can be written top-to-bottom and right-to-left. A property like margin-right may work perfectly for English, French, or Spanish, but once the site is translated into Arabic or Japanese, the layout may break or behave unexpectedly.
Logical properties to the rescue! Instead of using margin-right, we can use margin-inline-end, and the spacing will automatically adjust based on the writing direction. No more exceptions or extra code!
And if you think this isn't a real problem or you've never run into these issues... bless your soul. Consider yourself lucky... or unlucky, depending on how you feel about dealing with an annoying (yet interesting) challenge... but mostly annoying.
Returning to triangles and borders: using CSS logical properties is the exception.
Instead of writing:
.triangle {
width: 0;
height: 0;
border-bottom: 10px solid transparent;
border-top: 10px solid transparent;
border-left: 20px solid black;
}
Consider doing this:
.triangle {
width: 0;
height: 0;
border-block-start: 10px solid transparent;
border-block-end: 10px solid transparent;
border-inline-start: 20px solid black;
}
By using logical properties, the triangle will point to the right in English, to the left in Arabic, and downward in traditional Chinese or Japanese. In other words, the triangle will always follow the writing direction.
Let's check an example to understand why this matters. Imagine a breadcrumb component: you have a list of nested pages and want to place a small triangle between each item, like this:

If we use that same component on an Arabic site, the triangles still point to the right, while the text flows to the left. This happens when the triangles are created using images, clip-path, or even borders defined with physical properties.

Here's a CodePen demo showing the four triangle-drawing methods mentioned in this article. It lets you switch the text direction to right-to-left or top-to-bottom (or both). Notice how the only triangle that adapts naturally in all directions is the one created using borders with logical properties.
And that's the use case. The exception where using borders to draw triangles is actually the better option. But only when logical properties are involved.
I still don't like border triangles. But, in this one specific case, they become the best and easiest tool.