3

Always one of the boxes should be green and one red.

.elem {
  width:200px;
  height:200px;
  background-color:#911;
  margin:20px;
}

/* If at least 300px wide and the device is able to hover */
@media (min-width: 300px) and (hover: hover) {
    #carl {
       background-color:#191;
   } 
}

/* If maximum 300px wide OR the the device is not able to hover */
@media (max-width: 300px), (hover: none) {
    #dude {
       background-color:#191;
   } 
}

/* Try the exact opposite of the first media query also fails */
@media not all and (min-width: 300px, "bigheader")) and (hover: hover) { 
    #dude {
       background-color:#191;
   } 
}
<div id="carl" class="elem"></div>
<div id="dude" class="elem"></div>

Basically the second media query is doing the exact opposite of the first media query. Unfortunatly this is only working for browsers which are supporting CSS4 media interaction features media queries.

For Browsers like IE 11 which do not support it, both boxes are red and the second media query fails. However I want browsers to fallback on the second possibility in case the first is not supported. Can you help me out?

Blackbam
  • 17,496
  • 26
  • 97
  • 150
  • I submit that we don't really need a tag distinguishing interaction media features from other media features. This question is generally applicable to any media feature from Media Queries 4 and up anyway (see Media Queries 5). – BoltClock Oct 22 '18 at 14:34
  • @BoltClock Guess you are right this might be overly specific. Guess that media queries are used as a synonym for media features (https://www.quackit.com/css/css_media_features.cfm)? You have enough rep to delete the tag I guess. – Blackbam Oct 22 '18 at 14:41

3 Answers3

2

This is a little tricky; since the only way to apply styles for when a browser doesn't support a particular media feature is by taking advantage of the cascade, you'll need to apply the fallback style outside a @media rule altogether. This does come at a slight cost of duplicating some styles, unfortunately:

.elem {
  width:200px;
  height:200px;
  background-color:#911;
  margin:20px;
}

/* If maximum 300px wide OR the the device is not able to hover */
#dude {
  background-color:#191;
}

/* If at least 300px wide and the device is able to hover */
@media (min-width: 300px) and (hover: hover) {
  #carl {
    background-color:#191;
  }
  #dude {
    background-color:#911;
  }
}
<div id="carl" class="elem"></div>
<div id="dude" class="elem"></div>
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • This is sad as this can get very complicated. But it seems to be the only valid answer for CSS only. – Blackbam Oct 23 '18 at 14:08
1

You could use Modernizr to determine whether or not the browser supports hover media queries. If so it would place the class hovermq on <html>. You can form your media queries around whether or not this class exists.

Also, you may not want to set both your min-width and max-width at 300px, for at that width both media queries' styles will be applied. You could form them like so:

...
/* If at least 300px wide and the device is able to hover */
@media (min-width: 300px) and (hover: hover) {
    #carl {
       background-color:#191;
   } 
}

/* If maximum 300px wide OR the the device is not able to hover */
@media (max-width: 299px), (hover: none) {
    #dude {
       background-color:#191;
   } 
}

I have changed the max-width media query to 299px.

Dave
  • 168
  • 1
  • 9
0

I have solved the problem by adding some JavaScript and use classes on HTML like Modernizr does it, but as a no library solution:

(function($) {

    r2oBodySizeClasses()
    r2oBodyInteractionClasses();


    $(window).resize(function() {
       r2oBodySizeClasses();
    });

    function r2oBodySizeClasses() {
        if($(window).width() < 960) {
            $('html').removeClass('client-bigheader').addClass('client-smallheader');
        } else {
            $('html').removeClass('client-smallheader').addClass('client-bigheader');
        }

        if($(window).width() >= 1216) {
            $('html').removeClass('client-screen-small client-screen-medium').addClass('client-screen-large');
        } else if($(window).width() >= 640) {
            $('html').removeClass('client-screen-small client-screen-large').addClass('client-screen-medium');
        } else {
            $('html').removeClass('client-screen-medium client-screen-large').addClass('client-screen-small');
        }
    }

    function r2oBodyInteractionClasses() {
        $('html').removeClass("client-hover client-hover-none client-hover-unknown");
        if(window.matchMedia("(hover: hover)").matches || ((navigator.userAgent.search("Firefox") > -1) && screen.width >= 960 )) {
            $('html').addClass("client-hover");
        } else if(window.matchMedia("(hover: none)").matches) {
            $('html').addClass("client-hover-none");
        } else {
            $('html').addClass("client-hover-unknown");
        }
    }

}) (jQuery);

Still a CSS only solution would have been better ofc.

Blackbam
  • 17,496
  • 26
  • 97
  • 150