Search code examples
htmlcsspngstate

Changing states of buttons built using css + png


I'm trying to build styles for my buttons in the most efficient way. I have a class called .button-small that contain all the colors and dims for the buttons:

.button-small {
background: linear-gradient(to bottom,  #59aeee 1%,#4ea0dc 100%); /* W3C */
border-radius: 3px;
cursor: pointer;
width: 20px;
height: 20px;
}

To that class I'd like to add all required states, .button-small:active etc.

Now that is a simple part, the struggle comes next. I have several buttons and all of them have different png file, so I decided to create separate classes that would hold only additional information about image url, that is:

.user-chat {
background: url('images/userchat.png') center center no-repeat;
}

The problem with above is once applied to the HTML code, <div class="button-small user-chat"></div>, background: property is stripping off information about the color from the main .button-small class. I know I could add information about background to the code, which I did previously:

.user-chat {
background: url('images/userchat.png') center center no-repeat, linear-gradient(to bottom,  #73b5e7 1%,#429be0 100%)`
}

But than in order to add different button states to the code, I'd have to duplicate the code for each button, and since I have approximately 30 of them, that wouldn't be very efficient.

So what I'm really after is a line of code that would allow me to insert different transparent-background png images on top of the button, regardless the button's state. Is there such thing, and if not, what would be the most efficient way to get the job done?


Solution

  • You may wish to consider the use of pseudo elements. It's what I usually do when I need multiple background images like you're after.

    You could do something similar to this:

    .button-small {
        position: relative; /* So we can position our ::before element as needed */
    }
    
    /* Generic styles for pseudo elements */
    .button-small::before {
        content: ''; /* required for pseudo elements to work */
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
    }
    
    /* You would now add your additional classes */
    .user-chat::before {
        background: url(../something/goes/here.png) center center no-repeat;
    }
    

    This code should work in IE9 upwards. If you're supporting IE8, use :before instead of ::before.

    For the hover and active states, you could do:

    .user-chat:hover::before,
    .user-chat:active::before,
    .user-chat:focus::before {
        background-image: url(new/image.png); 
        /* Only need to override the image URL if position stays the same */
    }