Building HTML arrows is one of those tricks that seem simple, but hide much more depth than they appear. Experimenting with CSS over time, I have found that most of the arrows we see on the web are not images, but the result of playing with borders, pseudo-elements, and a bit of positioning.
In this guide, I will show you all the real ways to create arrows in HTML, from the simplest ones with entities, to advanced arrows with CSS and SVG, explaining when to use each one.
What building arrows in HTML means
When we talk about building arrows in HTML, we're not just referring to displaying a symbol → on the screen. In practice, arrows are used to:
- Indicate directions
- Guide the user in navigation
- Complement containers (tooltips, speech bubbles)
- Create forward/backward buttons
- Reinforce visual hierarchy
The most common mistake is to think that all arrows must be icons or images, when in reality HTML and CSS offer lighter, more flexible, and easier-to-maintain solutions.
What do we mean when we talk about arrows in containers?; well, an image is worth a thousand words:

It is a fork that is placed on a container; they are ideal for pop-up menus or simply for drawing text bubbles -boxes- which, in simple words, is placing arrows on the container with a bit of CSS; arrows for the right, left, bottom, and top sides with a little bit of HTML and some CSS.
Ways to create arrows in HTML (overview)
Before going into detail, these are the available options:
- HTML Entities / Unicode → simple and fast
- Pure CSS → arrows without images using borders
- CSS arrows on containers → tooltips and bubbles
- SVG → complex or animated arrows
- HTML + CSS + JavaScript → interactive navigation
The key is to choose the correct method based on the context, not always to use the most complex one.
Arrows using HTML entities (the simplest option)
HTML entities are the fastest way to add arrows to a text. They work the same as other known entities like © or π.
Basic arrows left, right, up, and down
Some common examples:
- Right arrow: → →
- Left arrow: ← ←
- Up arrow: ↑ ↑
- Down arrow: ↓ ↓
- Double right arrow: ⇒ ⇒
Example in HTML:
<p>Move to the right → next step</p>This approach is ideal when you only need to indicate direction within a text, without special styles.
When to use HTML entities and when not to
Use entities if:
- The arrow is part of the text
- You don't need custom styles
- You seek maximum compatibility
Avoid them if:
- You need to dynamically change size or color
- The arrow is part of a visual design
- It is integrated into buttons or containers
That's where CSS begins to shine.
Building arrows with CSS using borders
Here we enter the most interesting territory. When I started experimenting with arrows in CSS, I understood that I wasn't drawing arrows, but playing with invisible borders until one takes prominence.
The trick of border-width and transparent colors
The base is always the same:
.arrow { width: 0; height: 0; border-style: solid;}Then you decide:
- Which border is visible
- Which ones are transparent
- Where the arrow points
Example: right arrow
.arrow-right { border-top: 10px solid transparent; border-bottom: 10px solid transparent; border-left: 15px solid black;}<div class="arrow-right"></div>CSS arrows in the four directions
By changing the visible border you can create any direction:
- Right → border-left
- Left → border-right
- Up → border-bottom
- Down → border-top
This pattern is the basis of most CSS arrows you see in production.
Common mistakes when creating arrows with CSS
Based on experience, these are the most common mistakes:
- Forgetting width: 0 and height: 0
- Not making the other borders transparent
- Using incorrect relative positions
- Not calculating border sizes correctly
CSS arrows in containers and text bubbles
For this small CSS trick we will use a property already discussed in the previous post called Geometric shapes with CSS (part 2) ; in which we saw, through three examples, the versatility of the border-width property in conjunction with the :before and :after selectors.
The trick here, just like in the previously cited post, is to use the selectors :before and/or :after to create "another container" near the original container and give it the desired shape - with the border-width property - and position - with the left, bottom, and top properties.
Let's see in detail how to create these arrows in the containers.
Arrow in the container top and left
.top-left:before { content: ""; position: absolute; top: -25px; left: 0; width: 0; height: 0; border-width: 0 25px 25px; border-style: solid; border-color: transparent transparent red;}The pattern is always the same:
- ::before or ::after
- Absolute position
- Borders to create the shape
Position adjustment with top, left, and bottom
If you analyze several examples, you will see that the only thing that really changes is the position and the active border. In practice, moving an arrow is usually a matter of adjusting a few pixels until it fits visually.
Arrow in the container top and right
.top-right:before { content: ""; position: absolute; top: -25px; left: 50px; width: 0; height: 0; border-width: 0 25px 25px; border-style: solid; border-color: transparent transparent red;}Arrow in the container right side and bottom
.right-side-bottom:before { content: ""; position: absolute; top: 50px; left: 100px; width: 0; height: 0; border-width: 25px; border-style: solid; border-color: transparent transparent transparent red;}Arrow in the container right side and top
.right-side-top:before { content: ""; position: absolute; top: 0; left: 100px; width: 0; height: 0; border-width: 25px; border-style: solid; border-color: transparent transparent transparent red;}Arrow in the container left side and bottom
.left-side-bottom:before { content: ""; position: absolute; top: 50px; left: -50px; width: 0; height: 0; border-width: 25px; border-style: solid; border-color: transparent red transparent transparent;}Arrow in the container bottom and left
.bottom-left:before { content: ""; position: absolute; bottom: -25px; left: 0; width: 0; height: 0; border-width: 25px 25px 0; border-style: solid; border-color: red transparent transparent;}Arrow in the container bottom and right
.bottom-right:before { content: ""; position: absolute; bottom: -25px; left: 50px; width: 0; height: 0; border-width: 25px 25px 0; border-style: solid; border-color: red transparent transparent;}If you study the previous CSS a bit; you will realize that the only thing that varies is the position where the container is located with the properties top, bottom, and left; also, depending on the position, the side to which the border (border-width) and its color (border-color) are applied is defined, and with this, we give it the desired shape.
We can also create arrows without containers that are a little more attractive, that is, more arrows and fewer triangles, and use them individually wherever you want and they look like small arrow-shaped icons:
The HTML consists of two blocks:
<div class="triangulo abajo"><div></div></div>The CSS is the following:
.triangulo {
border-style: solid;
border-width: 18px;
width: 0;
height: 0;
}
.triangulo>div {
border-style: solid;
border-width: 10px;
width: 0;
height: 0;
position:relative;
}
.triangulo.derecha{
border-color: transparent transparent transparent black;
}
.triangulo.derecha>div {
border-color: transparent transparent transparent white;
top:-10px;
left:-21px;
}
.triangulo.izquierda{
border-color: transparent black transparent transparent;
}
.triangulo.izquierda>div {
border-color: transparent white transparent transparent;
top:-10px;
left:1px;
}
.triangulo.arriba{
border-color: black transparent transparent transparent;
}
.triangulo.arriba>div {
border-color: white transparent transparent transparent;
top:-21px;
left:-10px;
}
.triangulo.abajo{
border-color: transparent transparent black transparent;
}
.triangulo.abajo>div {
border-color: transparent transparent white transparent;
top:1px;
left:-10px;
}The operation is simple, as you can see we have a parent container that only consists of a border, defined with the border-width attribute.
Then for the div or inner container of the div with class triangulo we define another border-width and separately the border color, which can be four; one for each side, which we can also use as one for each type of arrow (right, left, up, or down):
border-color: transparent black transparent transparent;In the previous case, we only defined one color which in this case is for the left arrow; although we can use more than one color per side to make larger arrows.
Finally, to make that characteristic peak in the tail of the arrow and thus convert a triangle into an arrow, with the internal container to the triangle class, we create another smaller container and position it in the center of the figure:
top: -10px; left: 1px; Creating more realistic arrows: from triangles to arrows
A triangle works, but often looks too flat. When I tried combining two triangles, the result was much closer to a real arrow.
CSS arrows with double container
<div class="triangulo derecha"> <div></div></div>CSS (summary):
.triangulo {
border-style: solid;
border-width: 18px;
width: 0;
height: 0;
}
.triangulo > div {
border-style: solid;
border-width: 10px;
width: 0;
height: 0;
position: relative;
}How to simulate the “point” of an arrow
The second, smaller and offset triangle creates that central cutout that transforms a simple triangle into a visually more attractive arrow. This approach is ideal when you want CSS icons without relying on external libraries.
Arrows with SVG: when they are worth using
SVG makes sense when:
- You need complex animations
- You require vector precision
- You are going to reuse the arrow many times
HTML arrows for navigation and interaction
Arrows are often used as forward and backward buttons.
Arrows as buttons:
Using <button> is good practice for accessibility:
<button aria-label="Previous" class="btn-flecha"></button>Basic use with JavaScript:
document.getElementById("btn-siguiente").addEventListener("click", () => { console.log("Next");});Here, the arrow is only the visual part; the logic is provided by JavaScript.
Which method to choose to build HTML arrows
In summary:
- Simple text → HTML entities
- Light design → CSS with borders
- Tooltips and bubbles → pseudo-elements
- Animations → SVG
- Navigation → HTML + CSS + JS
There is no single correct solution, but the most appropriate one for each case.
Frequently Asked Questions about arrows in HTML
- Can arrows be created without images?
- Yes, and in fact it is the most recommended option using CSS or HTML entities.
- Which is better, CSS or SVG?
- CSS for simple arrows and UI. SVG for complex or animated graphics.
- Do CSS arrows affect performance?
- No, they are extremely light compared to external images or icons.
Conclusion
Building HTML arrows is an excellent example of how well-used HTML and CSS can replace images and icons. With a few borders, pseudo-elements, and some practice, you can create arrows that are flexible, scalable, and perfectly integrated into any web design.
I agree to receive announcements of interest about this Blog.
In this entry we will explain how to create containers with arrows or containers with a branch that we place in it, additionally, we see how we can create arrows using HTML code.