A CSS triangle fails to render correctly in four predictable ways during generation: a non-zero content box turns the shape into a trapezoid, an undeclared transparent border clobbers a coloured side, odd-dimension rounding quietly steals a pixel, and decorative accessibility markup is reused for meaningful state. Most of these problems live in the same handful of declarations - the element's content width and height, the four longhand border properties, and the lone aria attribute shipped in the HTML - which means the diagnosis can run in a fixed order before any code is copied into a stylesheet. Working through the failure modes in that fixed order, with a live preview at each step, is what separates a triangle that renders cleanly in every browser from one that looks correct in DevTools but breaks against a coloured background, at 200 percent zoom, or under forced-colour mode. The CSS Triangle Generator exposes those declarations side by side with a real preview, so each potential failure can be triggered on purpose and read off the screen instead of being hunted down after the page has shipped.

The four failure modes that break a generated CSS triangle
Border triangles look mysterious because every part of the shape is painted by a border, yet the element itself is supposed to contain nothing. That single inversion of expectation explains almost every reported bug. Any width or height greater than zero adds an inner rectangle underneath the painted borders, and at least one edge of that rectangle becomes the dominant visual line. Any border that is not explicitly transparent joins the geometry as solid colour. Any rounded value that looks correct on paper can shrink by one pixel after the browser quantizes halves. Any aria attribute that was written for a decorative separator can quietly strip meaning from a control that needed a label.
Each of these failure modes is recoverable in under a minute once the cause is named. The diagnostic table below maps the symptom on screen to the root cause in the declaration block and to the fix that the generator can apply.
| Symptom on screen | Root cause | What to inspect | Fix in the generator |
|---|---|---|---|
| Trapezoid with one shorter side | Forgotten width: 0 and height: 0 | The content box of the element | Re-set width and height; the generator enforces the zero-size rule |
| Triangle missing on one slope | A border was not declared transparent | All four longhand border colors | Reset direction so the two non-pointing sides read transparent |
| Triangle one pixel shorter than requested | Browser quantization on equal halves of an odd base | The total of the two transparent borders | Move to an even dimension or keep the 20/21 split the generator already chose |
| Visible in DevTools but silent to a screen reader | aria-hidden="true" on a meaningful shape | The HTML snippet and the surrounding control | Drop the decorative snippet and add labelled text to the interactive element |
Why a non-zero content box turns the shape into a trapezoid
The element that paints a border triangle has no painted content; its visible area is built out of four borders meeting at the corners. If width or height is left at the user-agent default, each border starts against an offset edge instead of a single shared point, and the four sloping corners no longer add up to a closed triangle. The browser fills the resulting rectangle with the element's normal background - which is transparent by default and therefore invisible - and the painted shape becomes a trapezoid whose short side equals the leftover width or height.
The MDN backgrounds and borders guide documents how transparent borders paint the diagonal corners. The CSS Backgrounds and Borders specification defines the longhand border widths, styles, and colors that the generator writes explicitly. Both sources confirm that the rule is mechanical, not magical: a non-zero content box still produces borders of the requested size, but the additional content area sits underneath them and offsets the corners. The generator renders the element at zero width and zero height so the corners collapse to a single point.
How odd dimensions and undeclared transparent borders lose pixels
Once the content box is zeroed out, the next failure point is the perpendicular dimension. A 41px wide upward triangle uses a coloured bottom border of 41px and two transparent side borders that together span the same 41px. Splitting that range into two equal halves gives 20.5px on each side. In practice, Chromium can quantize two 20.5px borders down to 20px each, and the painted triangle ends up one pixel narrower than the requested width.
The generator pre-empts that quantization by writing one border with floor and the other with ceiling, so 41px becomes 20px on one side and 21px on the other. The total stays exact, the geometry stays symmetrical to the eye, and there is no need to remember the workaround by hand. The same floor-and-ceiling split applies to vertical triangles across the width and to horizontal triangles across the height. Rasterization can still vary with browser zoom and with the device pixel ratio, so the preview is a guide, not a guarantee, for the final paint.
Use the CSS Triangle Generator to diagnose in real time
Running through the failure modes by hand works, but the diagnostic value of the CSS Triangle Generator is that the broken state and the working baseline sit next to each other on the same screen. The page exposes synchronized CSS and HTML panes, and the same border declarations are used for both the preview and the copied code. Direction, width, height, and a six-digit HEX colour are the only inputs; the rest of the geometry is derived from those four values.
Generation and copying happen in the current browser tab, so there is no upload, no account, and no saved design state to clear. Re-running the diagnostic with a different dimension or colour is therefore free. Several recurring symptoms - trapezoid, missing slope, lost pixel - have their own walkthroughs in the companion mistakes guide, which is a useful cross-check when the same bug keeps returning.
Diagnose a CSS triangle after generation in five ordered steps
- Set the inputs in the generator. Choose direction, width, height, and a six-digit HEX colour. Stay inside the documented range of ten to three hundred whole pixels for both width and height so the generator can derive the geometry from those values alone.
- Inspect the preview at the size and background where the triangle will live. Look for a trapezoid, a missing slope, a flat edge where a point should be, and any visible aliasing at 200 percent zoom. The preview uses the same border geometry that will be copied into the stylesheet.
- Read the CSS pane in declaration order. Confirm width is zero, height is zero, three borders are transparent, and one border carries the chosen colour. Every longhand is written explicitly so the geometry stays auditable from the start.
- Read the HTML pane and decide whether aria-hidden="true" still fits the context. If the triangle communicates state, direction, validation, or navigation, replace the decorative snippet with a labelled semantic control around it and remove the silent attribute.
- Copy CSS and Copy HTML one at a time. The two clipboard requests are separate, the status names the copied format, and a clipboard denial leaves both code blocks visible for manual selection. Rename the default class if it would collide with an existing stylesheet, then update both outputs together.
Theming, zoom, and accessibility surfaces that hide later
Some problems only show up after a triangle has been pasted into a real component. The first is theming: the generator's HEX colour is painted as an opaque border, and it will not follow a design token, a CSS variable, a gradient, a currentColor value, or any alpha or wide-gamut syntax. Replacing the literal in the copied CSS with a trusted token is reasonable, but the developer must verify that the target syntax is supported and that the transparent side borders stay transparent.
The second is contrast. A triangle that sits next to body copy should be checked in both light and dark themes rather than assumed to inherit enough contrast from its container. The third is forced-colour mode, where the user agent can replace any opaque colour with a system palette; border triangles painted with a single HEX value are particularly exposed to that override because there is no fill, stroke, or secondary token to fall back on. A short forced-colour pass at 200 percent zoom catches most of these issues before they reach a real user.
When the border trick is the wrong tool for the geometry
A border triangle is compact, dependency-free, and predictable up to a point. The predictable point ends where the shape needs anything more than a solid four-direction arrow: a rounded tip, a curved edge, a hollow centre, a gradient fill, a real stroke, a soft shadow, or an arbitrary polygon. The MDN guide is clear that those are not properties of borders; they belong to SVG and to clip-path. The generator is honest about that limit and refuses to invent a syntax that the underlying technique cannot express.
| Need | Border triangle | SVG | clip-path |
|---|---|---|---|
| Solid four-direction arrow in plain CSS | Suited | Suited, with extra markup | Suited, with extra markup |
| Rounded tip or curved edge | Not supported | Suited | Suited |
| Hollow shape, gradient, or stroke | Not supported | Suited | Suited |
| One decorative arrow beside text | Suited | Suited | Suited |
| Control that needs labelled semantics | Suited when paired with labelled text | Suited with role and label | Suited with role and label |
For a solid decorative triangle that points in one of four directions and stays under three hundred pixels, the generator is the shortest path from broken to correct. For anything else, the diagnostic stops at the limit and the developer picks SVG or clip-path and tests browser support in the intended environment. Knowing where to switch tools is itself part of the troubleshooting process.
Related reading: Troubleshoot Average Color From Image: What to Check First.