Icon replacement trick (when you cannot change the image in the markup)

Started by Antechinus, September 06, 2021, 06:17:10 PM

Previous topic - Next topic


This is my latest sneaky dodge.

I'm running this code live on this site via Stylus. That means I can't change the images that are called in the site's markup, since all I can do is play with CSS. The tiny crappy icons for topics you have posted in were bugging me, so I tried a variation of a trick I have used before.

Images (ie: the <img> tag) can accept padding and background images, just like most other HTML tags. Turns out they also accept other things like hidden overflow. This means you can:

1/ set a fixed size on the image you don't want to see (standard practice anyway)
2/ make this the same size as the image you want to see when you are finished.
2/ set the image to overflow: hidden;
3/ set a top padding to the same height as the image
4/ call in the image you want to see, as a CSS background image
5/ set background size: cover;

img.posted {
    overflow: hidden;
    width: 20px;
    height: 20px;
    margin: 5px -5px -5px;
    padding-top: 20px;
    background-image: url(https://static.simplemachinesweb.com/smf/smsite/images/icons/profile_hd.png);
    background-size: cover;

What this does is shunt the image you don't want to see out of view, and visually relace it with the one you want. The one you want can be any image you have a live url for.

An example is shown in the screenshot, calling the SMF profile_hd.png to replace the default profile_sm.png, and resizing it to 20x20. I've also added a -5px margin to get a more pleasing placement of the image.

Note: One important point is that it is essential that the image is set to box-sizing: border-box; - which is set on all elements anyway in SMF 2.1. If you want to use this trick outside of SMF 2.1, ensure that the CSS includes box-sizing: border-box; :)


DO NOT pm me for support!


I just tried this one today. I had done something similar before, when there was a handy parent element for the image (ie: wrapped in an span or whatever). That obviously works too, but with these icons there was no handy parent to put the hidden overflow on.

So, just for the heck of it I decided to try putting it on the image itself. Frankly, I did not expect it to work. I was pretty amazed and chuffed when it worked perfectly. :D


Ok, more trickery with icons for giggles. :P

I've been messing with the on/o2/off/redirect icons. This is calling the default sprite for those images, from this site...

All the changes in eye candy done with CSS, and it looks like this...

You cannot view this attachment.

The code for this result is geting a tad bonkers for one sprite, but it's interesting anyway. It goes like this:

/* ----------------------------------- */
/* @todo - May change if grid is used. */
.board_icon {
    order: 1;
    flex: none;
    width: 64px !important;
    padding-top: 11px;
/* ------------------------------- */
/* @todo - Board icons - animated. */
.board_on, .board_on2  {
    filter: sepia(1) hue-rotate(-10deg) saturate(1.6);
    animation: BoardOnPulse 3s infinite;
@keyframes BoardOnPulse{
    0% {
        opacity: .5;
    50% {
        opacity: .5;
    75% {
        opacity: .6;
    100% {
        opacity: .5;
/* ----------------------------- */
/* @todo - Board icons - static. */
.board_off {
mix-blend-mode: soft-light;
.board_redirect {
background-image: none !important;
position: relative;
.board_redirect::before {
position: absolute;
display: block;
width: 45px;
height: 45px;
content: '';
background: url(https://static.simplemachinesweb.com/smf/smsite/images/boardicons.png) no-repeat 0 0 / 90px;
background-position: -1px -41px;
    opacity: .3;
.board_redirect::after {
position: absolute;
display: block;
width: 45px;
height: 45px;
top: -2px;
left: 2px;
font-size: 3.125rem;
line-height: 1em;
content: '\21aa';
transform: scaleY(-1);
background: linear-gradient(90deg,#bb9c77,#eda85a);
color: transparent;
-webkit-background-clip: text;
background-clip: text;
text-shadow: 1px 1px 1px rgba(23,35,44,.3);
/* ------------------------------------------- */
/* @todo - Board icons - Hover, focus, active. */
.board_on:hover, .board_on:focus,.board_on:active,
.board_on2:hover, .board_on2:focus,.board_on2:active {
    animation: none;
    opacity: .9;
.board_redirect:hover::before, .board_redirect:focus::before,.board_redirect:active::before {
    opacity: .6;
.board_redirect:hover::after, .board_redirect:focus::after,.board_redirect:active::after {
background: #ffb866;
-webkit-background-clip: text;
background-clip: text;
The redirect icon is now using the default off icon, in a ::before pseudo instead of directly on the anchor. This is so I can adjust the looks of it independently of the ::after pseudo, which holds the bendy arrow thing as its content. Bendy arrow thing is a standard UTF8 \21aa that has had a -1 transform on the Y axis applied to it. All gets quite bonkers, but it's fun, and a good way to learn new tricks and get more ideas.  :)