Personalizing list elements with SVG symbols

I have been experimenting with customizing the bullet points of an unordered list in HTML by using icons that I sourced from various websites. Here is the SVG code for the first icon, which is stored in home.svg:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
    stroke="blue" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
    class="feather feather-home">
    <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
    <polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>

And here is the SVG code for the second icon, which is stored in linkedin.svg:

<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="blue"
  class="bi bi-linkedin" viewBox="0 0 16 16">
  <path
    d="M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854V1.146zm4.943 12.248V6.169H2.542v7.225h2.401m-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248-.822 0-1.359.54-1.359 1.248 0 .694.521 1.248 1.327 1.248h.016zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016a5.54 5.54 0 0 1 .016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225h2.4" />
</svg>

In my HTML document, I've created a simple unordered list with list items assigned different classes:

And in my styles.css file, I have associated each of these classes with either home.svg or linkedin.svg:

ul
{
    list-style-type: none;
}

li.first::before
{
    display: inline-block;
    width: 16px;
    content: url('home.svg');
}

li.second::before
{
    display: inline-block;
    width: 16px;
    content: url('linkedin.svg');
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <ul>
        <li class="first">First item</li>
        <li class="second">Second item</li>
    </ul>
</body>
</html>

Although this setup works and displays the icons correctly, there are some issues with inconsistent sizes and alignment with the text content of the list items.

Is there a way to standardize the sizes of the icons and ensure they align properly with the text?

ul {
  list-style-type: none;
}

li.first::before {
  display: inline-block;
  width: 16px;
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='blue' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-home'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3Cpath%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E");    
}

li.second::before {
  display: inline-block;
  width: 16px;
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='blue' class='bi bi-linkedin' viewBox='0 0 16 16'%3E%3Cpath d='M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854V1.146zm4.943 12.248V6.169H2.542v7.225h2.401m-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248-.822 0-1.359.54-1.359 1.248 0 .694.521 1.248 1.327 1.248h.016zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016a5.54 5.54 0 0 1 .016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225h2.4' /%3E%3C/svg%3E");    
}
<ul>
  <li class="first">First item</li>
  <li class="second">Second item</li>
</ul>

Answer №1

To control the gap between the icon and text, as well as align them vertically, apply flexbox to the list items.

Additionally, use flexbox on the pseudo-elements that contain the icons to ensure they are centered within their respective elements.

You can adjust the width and height attributes within each SVG to make all icons appear the same size. However, a more efficient approach would be to set an optimum size for all icons and edit them accordingly in an SVG editor. Alternatively, consider using an icon pack designed with consistent sizing and style for all icons needed.

body {
  margin: 1em;
}

ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
}

li {
  display: flex;
  align-items: center;
  gap: 0.5em;
  margin: 0.5em 0;
}

li::before {
  width: 20px;
  height: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
}

li:nth-child(1)::before {
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='blue' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-home'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3C/path%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E");    
}

li:nth-child(2)::before {
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='blue' class='bi bi-linkedin' viewBox='0 0 16 16'%3E%3Cpath d='M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854V1.146zm4.943 12.248V6.169H2.542v7.225h2.401m-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248-.822 0-1.359.54-1.359 1.248 0 .694.521 1.248 1.327 1.248h.016zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016a5.54 5.54 0 0 1 .016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225h2.4' /%3E%3C/svg%3E");    
}
<ul>
  <li>First item</li>
  <li>Second item</li>
</ul>

Answer №2

When placing SVGs using the content property, the intrinsic dimensions will be respected if defined by the width and height in the data URL.

Here is an exaggerated example:

ul {
  list-style-type: none;
}

li.first::before {
  display: inline-block;
  width: 16px;
  content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 24 24' fill='none' stroke='blue' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-home'><path d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z' /><polyline points='9 22 9 12 15 12 15 22' /></svg>");
}

li.second::before {
  display: inline-block;
  width: 16px;
  content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='blue' class='bi bi-linkedin' viewBox='0 0 16 16'><path d='M0 1.1c0-.6.5-1.1 1.2-1.1h13.6c.7 0 1.2.5 1.2 1.1v13.8c0 .6-.5 1.1-1.2 1.1h-13.6c-.7 0-1.2-.5-1.2-1.1zm4.9 12.3v-7.2h-2.4v7.2h2.4m-1.2-8.2c.9 0 1.4-.6 1.4-1.3s-.5-1.2-1.3-1.2-1.4.5-1.4 1.2.5 1.3 1.3 1.3zm5 8.2v-4c0-.3 0-.5 0-.6.2-.5.6-.9 1.3-.9s1.2.7 1.2 1.6v3.9h2.4v-4.1c...
}
<ul>
        <li class="first">First item</li>
        <li class="second">Second item</li>
    </ul>

The first icon is rendered at 100x100 px even though the pseudo element's width is specified as 16px.

To prevent this issue, you can easily remove the width and height attributes from your embedded SVG in the data URL like this:

ul {
  list-style-type: none;
}

li:before{
  display: inline-block;
  width: 1em;
  margin-right:0.5em;
}


li.first::before {
  content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='blue' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-home'><path d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z' /><polyline points='9 22 9 12 15 12 15 22' /></svg>");
}

li.second::before {
  content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' fill='%230000ff' class='bi bi-linkedin' viewBox='0 0 16 16'><path d='M0 1.1c0-.6.5-1.1 1.2-1.1h13.6c.7 0 1.2.5 1.2 1.1v13.8c0 .6-.5 1.1-1.2 1.1h-13.6c-.7 0-1.2-.5-1.2-1.1zm4.9 12.3v-7.2h-2.4v7.2h2.4m-1.2-8.2c.9 0 1.4-.6 1.4-1.3s-.5-1.2-1.3-1.2-1.4.5-1.4 1.2.5 1.3 1.3 1.3zm5 8.2v-4c0-.3 0-.5 0-.6.2-.5.6-.9 1.... 
}
<ul>
  <li class="first">First item</li>
  <li class="second">Second item</li>
</ul>

However, ensure that all icons' viewBox values are appropriate.

Credit goes to Danny '365CSI' Engelman's insights shared in other posts highlighting that modern browsers can handle less escaped or URL encoded svg markup in Data URLs by replacing double quotes with single quotes for attribute values and %23 with #, making it easier to write more readable CSS code.

Answer №3

An alternative solution that circumvents the need for flexbox and still allows room for adjusting marker icon size and padding is outlined below:

ul
{
padding: 0;
}

li:nth-child(1) {
  list-style: none;
  padding: 10px 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='blue' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-home'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3C/path%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left center;
  background-size: 20px;
}

li:nth-child(2) {
  list-style: none;
  padding: 10px 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='blue' class='bi bi-linkedin' viewBox='0 0 16 16'%3E%3Cpath d='M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854V1.146zm4.943 12.248V6.169H2.542v7.225h2.401m-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248-.822 0-1.359.54-1.359 1.248 0 .694.521 1.248 1.327 1.248h.016zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016a5.54 5.54 0 0 1 .016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225h2.4' /%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left center;
  background-size: 20px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8>
<title></title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<ul>
    <li>First item</li>
    <li>Second item</li>
</ul>
</body>
</html>

Admittedly, this approach may be considered unconventional or an exploitation of background-image, but it serves its purpose for now.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When hovering over the menu, the sub-menu is displayed and the content slides downwards. Is there a way to prevent the content from sliding down and have the sub-menu overlap the

When the main menu is hovered over, a sub-menu appears and the content below the main menu slides down. Check out the code snippet below: HTML: <div id="holderDiv"> <div id="menu"> <a href="#" id="items">Menu 1</a> < ...

concentrate on maximizing a complete table

I am facing an issue where I want to focus on a full table when it is selected, but unfortunately, clicking on the table does not trigger the focus effect. In an attempt to work around this problem, I tested the hover effect on the table and it worked per ...

Issues with PHP login session not being established when logging in with an SQL database

Lately, I've set myself a new challenge - creating a functional login screen for a website I'm building for my friends. However, despite inputting the email and password from my SQL database correctly, the validation file I'm using doesn&apo ...

Incorrect implementation of Bootstrap CSS in Jade template

Currently, I am leveraging Express to construct a website. However, there seems to be an issue with my jade template not displaying the bootstrap grid system accurately. Despite double-checking that my app path is correctly set through app.use(express.stat ...

Leveraging package.json information within HTML using ReactJS

Currently, I am facing a situation where I need to incorporate the name attribute from the package.json file into my HTML code in order to use it as the title of the document. While I am aware that this can be achieved through the use of the react-helmet ...

Having trouble updating the icon on my website using FontAwsome

Just a heads up - I'm not familiar with HTML/CSS/JS. This template is pre-made, and I'm simply making some adjustments to it. Hello, I'm currently working on my portfolio website and I want to display my projects based on the programming la ...

Issue with Dynamic Image Path in Require Function: Unable to locate the relative module

I've been struggling with an error in VueJs require function for the past two days. I'm attempting to pass a prop to the Home component and then display the image. Home.vue <template> <BlogPost :post="welcomeScreen"/> <B ...

JavaScript (Create a button that toggles the visibility of an element)

I have implemented a hamburger menu that transforms into an x when clicked. I am looking to modify it so that clicking on the hamburger opens the menu, and clicking on the x closes the menu. Below is the code I have been working with: <!DOCTYPE html&g ...

Tips for making a Google Map API Element fit perfectly in a Bootstrap column below a heading

I've spent countless hours trying to solve this on my own, scouring the internet for answers with no luck. I'm hoping someone here can spare a few moments to help me out. Much appreciated! I'm attempting to make the Google Maps API element ...

Is it possible to incorporate Node.js for form submission on a static website?

Currently, my website only consists of a home page and a contact page with navigation done through HTML and href links. To handle form submission on the contact page, I have set up a node.js server using express, nodemailer, and nodemailer-mailgun-transpo ...

Ways to move upward from a lower position

I am trying to create a hover effect where the title and content move to the right position upon hovering. The issue I am facing is that the transition on the `Title` class is not working, and as a result, the hover effect is also not functioning properly ...

Single-line form with labels positioned above the input fields

For my web app project, I am using AngularJS and Bootstrap 3 for CSS (although my CSS knowledge is limited). I am trying to design an inline form with 5 input fields and labels positioned on top of them. The first field should take up more space than the o ...

Unable to insert HTML code into a div upon clicking an image button

I am in the process of developing a website dedicated to radio streams, and I was advised to utilize Jquery and AJAX for loading HTML files into a div upon button click. This way, users wouldn't have to load an entirely new page for each radio stream. ...

Spinning the Dial using CSS

I have this SVG image (displayed below) and I am looking to create a continuous animation on the meter dashboard hand. The animation I want involves it (the meter hand) rotating 90 degrees to the left and then 90 degrees to the right. Usually, the CSS prop ...

Ensure that the background image adjusts appropriately to different screen sizes while maintaining its responsiveness

Currently in the process of developing a single page application using CRA. My goal is to create a hero image with an overlay at the top of the application using a background image. However, I'm facing issues with maintaining the responsiveness of the ...

What is the best way to ensure that the size and maximum length of a text input box are properly aligned?

Is there a way to ensure that the size and maxlength attributes of a text input box align correctly? It can be frustrating when these attributes don't match up due to font differences. Example Input: <input type="text" size="4" maxlength="4" /> ...

Utilizing CSS Media Queries for Page Layout Adaptation

After previously asking about a different issue with this project, I have encountered yet another problem. The task at hand requires using three distinct media queries to alter the page layout depending on the screen size in use (currently being tested by ...

Ensure that the mask implemented in the form input only shows two decimal places, while simultaneously retaining the original value

Is there a way to format a number in a form input so that it displays only two decimals while still retaining the original value? This is necessary to avoid incorrect values down the line and meets the customer's requirement of showing no more than tw ...

Angular checkbox utilizing an off-screen input element

Having an issue with Angular checkbox and would greatly appreciate any help: HTML: <span for="check" tabindex="0" role="checkbox" (click)="inputCheck.click()" (keydown)="keyEvent()"> <label for="check">checkbox</label> <input ...

Tips for merging two text boxes in a form with CSS

Is it possible to combine two text boxes in a form using CSS, similar to the design on Tumblr's login page at ? If CSS is not the solution, what alternative methods can be used? Any assistance would be greatly appreciated. I am aiming to enhance the ...