Is it possible to reverse colors on a button with CSS on hover


#1

Let’s say I have a blue button with white text. On hover, I’d like to turn it into a white button with blue text. Is this possible in CSS (without JavaScript)? Dynamically… (I’m trying to write reuseable code that will automatically take the font color and background colors and reverse them on hover, whatever they may be). I was thinking of using jQuery to get those color values from the elements and flipping them, but couldn’t get that working.

https://jsfiddle.net/catlovergeek/2gu3f0ws/45/


#2

Certainly.

.MyButton {
   background: #00f;
   color: #fff;
}

.MyButton:hover, .MyButton:focus {
   background: #fff;
   color: #00f;
}

#3

I was going to suggest that too, @SamA74, but then I reread the post and I think the OP means not knowing in advance what the colours are, can you reverse them on hover without using JavaScript?

I don’t think that is possible without JavaScript to figure what colours are being used, is it?


#4

I think it could be done with CSS variables. :thinking:
Depends on exactly what the OP want to happen.

.MyButton {
   background: var(--bg-color);
   color: var(--fg-color);
}

.MyButton:hover, .MyButton:focus {
   background: var(--fg-color);
   color: var(--bg-color);
}

…where the variables have previously been defined.


#5

This could be the tricky bit, if there are any number of different combinations in the site.
Still new to CSS variables, so don;t know their full capabilities.


#6

I think you could have limited success using ‘filter’

e.g.

I just typed that in on my phone so excuse the code. Maybe someone who has access to a computer can play around with it :slight_smile:


#7

A bit of an experiment with variables:-


#8

Hi there marianstevens,

Here is a very, very, silly example, although I did use variables…

<!DOCTYPE HTML>
<html lang="en">
<head>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1">

<title>A very, very, silly button</title>

<link rel="stylesheet" href="screen.css" media="screen">

<style media="screen">
body {
    background-color: #f9f9f9;
    font: 100% / 162% verdana, arial, helvetica, sans-serif;
 }

button {
    --bg-color: #00f;
    --fg-color: #fff;
 }

button {
    position: relative;
    display:block;
    width: 8.5em;
    height: 2em;
    margin: auto;
    border: 0.2em double #009;
    background-color: var( --fg-color );
    box-shadow: 0.2em 0.2em 0.2em rgba( 0, 0, 0, 0.3 );
    font-size: 2em;
    font-weight: bold;
    overflow: hidden;
    cursor: pointer;
 }

button::before,
button::after  {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 2em;
    background-color: var( --bg-color );
    content: '';
 }

button::after {
    line-height: 1.62em;
    background-color: transparent;
    content: 'A Silly Button';
    color: var( --fg-color );
    text-align: center;

 }

button:focus::before,
button:hover::before,
button:active::before {
    animation: change1 2s ease-in-out forwards;
}

button:focus::after,
button:hover::after,
button:active::after {
    animation: change2 2s ease-in-out  forwards;
 }

@keyframes change1 {
    100% { 
           left: -100%; 
         }
 }

@keyframes change2 {
    100% { color: var( --bg-color );
           transform: rotateY( 1440deg );
         }
 }

</style>

</head>
<body> 

  <button></button>

</body>
</html>

coothead


#9

If you use Sass, you can make a “button” mixin and pass colors as parameters for it. Works lovely.


#10

If you use inverse colours for the background and foreground then you can change them automatically using the invert filter as I suggested above.

Modern browsers only.


#11

The invert filter won’t change blue to white and vice versa. You would have to use blue and yellow or black and white.
Looking as support for filters and variables, both do most main browsers, excluding IE with Edge having some quirks. But variable support seem marginally better.
https://caniuse.com/#search=filter
https://caniuse.com/#search=variables

So with variables it would be a case of defining the colours for each different button class as variables, then applying a “swap” class too.


#12

No, as I said you need to use inverse colours for the background and the foreground to start with and then the colour change is automatic. That’s the main drawback apart from browser compatibility.

None of the other methods in this thread are exactly automatic as you are simply defining the hover colors somewhere else although the variable method is a good approach and probably the best method in this case.


#13

I did some experimenting. Granted my vision and tastes might be peculiar, but I have trouble with “mid” color values eg. 5-A because the inverse colors don’t have enough contrast for my liking. The “outer” values eg. 0-4, B-F have better contrast, but some of the combinations are a bit too garish for my taste.

Just the same, I think with a lot of experimentation some acceptable values could be found.


#14

That is the other issue with inverted colours, it does limit the choice of colour combinations.
Combinations like black & white and blue & yellow work well, being aesthetically complimentary with good contrast.
But combinations like red & cyan and magenta and green are a bit garish for me.


#15

Hi there marianstevens,

as this project is totally presentational and of no real
importance, I would go with a javascript solution. :winky:

I don’t believe that your visitors would care about it
working one way or the other. :unhappy:

Here is a basic example…

<!DOCTYPE HTML>
<html lang="en">
<head>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1">

<title>untitled document</title>

<link rel="stylesheet" href="screen.css" media="screen">

<style media="screen">
body {
    background-color: #f9f9f9;
    font: 100% / 162% verdana, arial, helvetica, sans-serif;
 }
button {
    display: block;
    min-width: 4em;
    padding: 0.25em 0;
    margin: 0.3em auto;
    font-size: 2em;
    font-weight: bold;
 }
#but1 {
    background-color: #121212;
    color: #fff;
 }
#but2 {
    background-color: #f00;
    color: #eff;
 }
#but3 {
    background-color: #00f;
    color: #ff0;
 }
#but4 {
    background-color: #080;
    color: #fef;
 }
</style>

</head>
<body> 

 <button id="but1">one</button>
 <button id="but2">two</button>
 <button id="but3">three</button>
 <button id="but4">four</button>

<script>
(function(w, d ) {
   'use strict';
   var c, bg = [], fc = [], but = d.getElementsByTagName( 'button' );

   for (c = 0; c < but.length; c ++ ) {
   bg[ c ] = w.getComputedStyle( but[ c ] ).getPropertyValue( 'background-color' );
   fc[ c ] = w.getComputedStyle( but[ c ] ).getPropertyValue( 'color' );
      but[ c ].addEventListener( 'mouseover', doStuff(c), false );
      but[ c ].addEventListener( 'mouseout', doStuff(c), false );
   }
function doStuff( c ) {
   but[ c ].onmouseover = function() {
   but[ c ].style.backgroundColor = fc[ c ];
   but[ c ].style.color = bg[ c ];
   }
   but[ c ].onmouseout = function() {
   but[ c ].style.backgroundColor = bg[ c ];
   but[ c ].style.color = fc[ c ];
   }
 }
}(window, document ));
</script>

</body>
</html>

coothead


#16

Although the OP seems to have left the building this recent article seems slightly pertinent (for interests sake only).


#17

I noticed that, but it was an interesting challenge and I learnt a little about the potential of css variables, so still a nice topic.