A CSS3 triangle generator builds the classic zero-size border triangle that is still defined by the CSS Backgrounds and Borders Level 3 specification. The trick sets an element's content width and content height to zero, lets two transparent borders form the two slopes, and assigns one opaque border to the side the triangle points toward. The CSS Triangle Generator lets a visitor pick one of four directions, enter width and height between ten and three hundred pixels, and supply a strict six-digit HEX color, then renders a live preview painted by the same longhand border declarations that appear in the copied output. CSS and HTML are kept synchronized, generation runs entirely in the current browser tab, and the snippet contains no script, remote request, image file, or external dependency. For decorative arrows, separators, and tooltip pointers, this border-only approach is compact, dependency-free, and easy to audit. The rest of this article walks through how the border trick paints a triangle, the four-direction recipe, the floor and ceiling split that keeps odd dimensions exact, the accessibility treatment the generator applies by default, and the honest limits to know before shipping a CSS3 triangle.

How the CSS3 Border Trick Paints a Triangle
The visible shape is painted entirely by borders, not by the element's content box. The element's content width and content height are both set to zero, so there is no painted content area to display. The triangle is then formed by three of the four border declarations: two transparent borders become the two sloping sides, and one colored border becomes the base or tip that points in the chosen direction. The CSS Backgrounds and Borders Level 3 specification defines each longhand border width, style, and color independently, which is why the implementation writes every declaration explicitly instead of relying on shorthand. MDN's CSS backgrounds and borders guide documents the transparent color behavior that lets the slopes vanish while the colored border keeps its full thickness.
When the colored border is on the bottom, the triangle points up. When the colored border is on the top, the triangle points down. When the colored border is on the left, the triangle points right. When the colored border is on the right, the triangle points left. In every case the element itself measures zero pixels in both dimensions, while the painted borders together occupy the full requested width and height. This is why a border triangle cannot be treated like a normal block element: it has a zero-size content box but a non-zero painted area, which affects layout, hit testing, and alignment.
Generate a CSS3 Triangle Step by Step
- Choose the triangle direction (up, down, left, or right), enter the visible width and height, and supply a six-digit HEX color prefixed with a hash. Whole values from ten through three hundred pixels are accepted, and the HEX must match the strict hash-plus-six-hexadecimal-digits pattern. The page immediately rejects unsupported directions, malformed colors, decimals, and values outside the stated range without silently clamping.
- Inspect the live preview at the approximate size and against the background where the triangle will actually be used. The preview is painted by the same derived border declarations that appear in the CSS output, so what you see is what you will copy. Check contrast against both light and dark surroundings if the triangle sits next to text.
- Copy the CSS and HTML separately. Each copy request asks for clipboard permission individually and reports a successful status naming the copied format. Preserve the aria-hidden="true" attribute if the triangle is purely decorative. If the triangle communicates state, direction, validation, or navigation, replace or remove it and add visible text or an accessible label on the surrounding control. If the generated class would conflict with an existing stylesheet, rename the lizely-triangle class in both outputs and update them together.
Direction Recipe Cheat Sheet
The four-direction recipe is built on a simple rule: the colored border lives on the side the triangle points away from. For up and down, the colored border is the top or bottom border and the two transparent side borders add up to the requested width. For left and right, the colored border is the left or right border and the two transparent top and bottom borders add up to the requested height. The colored border always carries the full pointing dimension.
| Direction | Left border | Right border | Top border | Bottom border |
|---|---|---|---|---|
| Up | transparent (width split) | transparent (width split) | 0 | height (color) |
| Down | transparent (width split) | transparent (width split) | height (color) | 0 |
| Right | 0 | width (color) | transparent (height split) | transparent (height split) |
| Left | width (color) | 0 | transparent (height split) | transparent (height split) |
Even dimensions split cleanly into two equal halves. Odd dimensions use floor and ceiling values, which the next section covers in detail.
Odd Base Dimensions and the Floor/Ceiling Split
For vertical triangles (up and down), the two transparent side borders must add up to the selected width, and the colored border must equal the selected height. For horizontal triangles (left and right), the two transparent top and bottom borders must add up to the selected height, and the colored border must equal the selected width. The split between the two transparent borders matters when the perpendicular base is an odd number of pixels.
Chromium can quantize a single 20.5px border down to 20px, so two 20.5px borders would silently become two 20px borders and lose a full pixel of the requested base. Splitting 41 into 20 and 21, written as 20px and 21px, keeps the painted total exactly 41px because the ceiling value compensates for the floor value. Even dimensions like 40 split cleanly into 20 and 20, since floor and ceiling of an even integer are equal.
Worked example for an upward triangle with width = 41, height = 50, color = #007bff: border-left becomes 20px solid transparent, border-right becomes 21px solid transparent, border-bottom becomes 50px solid #007bff, and border-top stays at zero. The two transparent side borders add up to 20 + 21 = 41 pixels, exactly matching the requested width, while the colored border supplies the full 50 pixel height. The output never silently drops a pixel from a request, and it never silently clamps a value either; unsupported input is rejected outright.
Accessibility and the aria-hidden Choice
The default HTML snippet contains a single div with the generated class and aria-hidden="true". That attribute hides the triangle from assistive technology, which is the correct treatment when the shape is purely decorative, such as a tooltip pointer, a separator below a heading, or an arrow that has no meaning apart from being a visual flourish. Decorative shapes should be hidden so screen readers do not announce empty or meaningless content.
If the triangle communicates state, direction, validation, or navigation, do not rely on the silent snippet alone. Add visible text or an accessible label to the surrounding interactive control, and keep the decorative triangle hidden from assistive technology. For example, a dropdown arrow next to a "Sort by" label should keep the visible label and use the triangle only as decoration; a previous and next button whose only content is a triangle needs an accessible name on the button element itself.
A triangle used next to text should also be checked in light and dark themes rather than assumed to inherit sufficient contrast. The chosen HEX color is painted as an opaque border, so alpha colors, gradients, currentColor, wide-gamut syntax, and theme tokens are not generated by the focused tool. After copying, replacing the literal with a trusted design token can improve theming, but verify that the target syntax is supported in the destination stylesheet and that the transparent side borders remain transparent.
What the Border Trick Cannot Do
Border triangles are compact but have real limits. The element's measurable content box is zero while its painted borders occupy space, which makes layout, transforms, hit testing, outlines, overflow, and alignment less intuitive than an SVG with an explicit viewBox. A border triangle cannot directly create a rounded tip, a curved edge, a hollow shape, a gradient fill, a stroke, a complex shadow, or an arbitrary polygon. For those needs, use SVG or clip-path and test browser support in the intended environment.
| Feature | Border triangle | SVG / clip-path |
|---|---|---|
| Solid straight-edge shape | Yes | Yes |
| Four directions (up, down, left, right) | Yes | Yes |
| Rounded tip or curved edge | No | Yes |
| Gradient fill or stroke | No | Yes |
| Hollow or outlined shape | No | Yes |
| Arbitrary polygon or diagonal | No (four directions only) | Yes |
| ViewBox-based scaling | No | Yes |
| Pure CSS, no markup file | Yes | No (SVG) / Depends (clip-path) |
If the design only needs a solid decorative triangle, the border approach is the lightest option available. If the design needs curves, strokes, gradients, or any shape beyond the four cardinal directions, the right tool is SVG or clip-path instead.
Test the Triangle Before Shipping
Performance cost for a single triangle is negligible, but hundreds of decorative elements can still increase DOM and paint work. Prefer one semantic control with a decorative shape over duplicated hidden controls. Test the final result at 200 percent zoom, high contrast, and forced colors mode, plus common mobile widths. The preview confirms the border geometry, not the complete accessibility or layout behavior of a destination component, so plan a separate check of the surrounding component layout, transforms, hit testing, outlines, overflow, and alignment.
Rasterization can vary with zoom and device pixel ratio, so what the preview shows at 100 percent may differ slightly at 200 percent or on a high-density display. A pixel that looked crisp at 100 percent can soften on a 3x mobile screen, and a 1px asymmetry that mattered on a wide desktop monitor may be invisible on a small phone. Run the result through the destination component, the destination stylesheet, and the destination device list before considering the triangle shipped.
Finally, verify that the class name lizely-triangle does not collide with an existing stylesheet, and update both CSS and HTML together if it does. A class name conflict can silently overwrite declarations and produce unexpected colors, sizes, or directions in the destination page. If the browser policy denies clipboard access during the copy step, both code blocks remain visible on the page for manual selection, and the tool does not falsely report a successful copy.