menu

Questions & Answers

Proper way to replace bullets with background-image

I want to replace bullets with images but I can't position them properly. I was doing the following:

.list-item::before {
  background: url(../myimg.png);
  background-size: contain;
  content: '';
  display: inline-block;
  width: 1.5em;
  height: 1.5em;
  margin: 0 1.5em -0.5em 0;
}

Which kind of worked until I realized when my li contains more than a line of text the text on the second line goes up to the left of the image of course because it's inline-block, which I don't want (see: https://ibb.co/GkrHhqC).

What I want is something like this (see: https://ibb.co/wJ5ktQc). Except to do that I used

.list-item::before {
  content: '';
  display: block;
  position: absolute;
  width: 1.5em;
  height: 1.5em;
  margin: 0 1.5em -0.5em 0;
  left: 1em;
}

Except it's cheating because the left means nothing. I'd like to position an absolute block, but relative to the left of my text. Is there a way to do that?

Answers(2) :

2 options spring to mind:

1. You could do this with grid

ul {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 20ch; /* just to force text wrapping */
}

li {
  display: grid;
  grid-template-columns: 2em 1fr;
  margin-bottom: 1em;
  gap: 0.5em;
}

li::before {
  content: '';
  background: skyblue; /* replace with your image bg */
  aspect-ratio: 1;
}
<ul>
  <li>Item</li>
  <li>Item</li>
  <li>Item with longer, wrapping text. Item with longer, wrapping text.</li>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
</ul>

2. You could use padding in the li to push the content right and position your image within the padding:

:root {
  --list-image-size: 1.5em;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 20ch; /* just to force text wrapping */
}

li {
  position: relative;
  padding-left: calc(var(--list-image-size) + 0.5em);
  margin-bottom: 1em;
}

li::after {
  content: '';
  width: var(--list-image-size);
  height: var(--list-image-size);
  position: absolute;
  top: 0;
  left: 0;
  background: skyblue; /* replace with your image bg */
}
<ul>
  <li>Item</li>
  <li>Item with longer, wrapping text</li>
  <li>Item</li>
  <li>Item</li>
</ul>

Comments:
2023-01-25 00:20:03
Grid seems to do the trick. But it's the first time I use it. How do I set the margins between the columns? And what does fr mean? And ch for that matter?

why not use a grid instead? Something like this

.list-item {
  display: grid,
  grid-template-columns: min-content 1fr; /* or min-content max-content*/
}

.list-item::before {
  content: '';
  display: block;
  width: 1.5em;
  height: 1.5em;
}
Comments:
2023-01-25 00:20:03
Oh my god I haven't even heard of grid before... Thank you so much.