Esto es un poco similar a una respuesta anterior, pero pensé que lo desarrollaría y lo explicaría completamente.
Tan pronto como lo establezca display: inline-block, se :afterconvierte en un elemento sin enlace de texto. Es por eso que envuelve y por qué nowrap no tiene ningún efecto. Así que vetedisplay paz.
Como es un elemento de texto por defecto, el contenido se vincula al texto anterior, siempre que no haya espacios en blanco entre ellos. Así que no agregue ninguno, pero asegúrese de tenerlo content: "", o es lo mismo que display: none. El único problema es heighty widthestán controlados por el content, que en este caso está colapsado. Así widthes 0, y heightes la altura de la línea.
Cambie el tamaño del área con relleno; izquierda o derecha, no importa. Agrega un poco marginpara que el ícono no toque el texto. Mantener todo lo más tamaños relativos ( em, pt, etc.), y el uso background-size: contain, por lo que las escalas de icono con el texto, como un emoji o de la fuente. Finalmente coloque el icono donde desee background-position.
ul li.completed a:after {
content: "";
background: url('icon.svg');
background-size: contain;
background-repeat: no-repeat;
background-position: center center;
margin-left: 0.2em;
padding-right: 0.75em;
}
He usado esto para mis enlaces externos ( a[href*="://"]:after) y ha funcionado bien en Firefox, Chrome e iOS. Y dado que el icono sigue siendo un elemento de texto, incluso el texto directo después de enlazarlo, por lo que cualquier puntuación de cierre también se ajustará.