718

Using conditional comments it is easy to target Internet Explorer with browser-specific CSS rules:

<!--[if IE 6]>
...include IE6-specific stylesheet here...
<![endif]-->

Sometimes it is the Gecko engine (Firefox) that misbehaves. What would be best way to target only Firefox with your CSS rules and not a single other browser? That is, not only should Internet Explorer ignore the Firefox-only rules, but also WebKit and Opera should.

Note: I'm looking for a 'clean' solution. Using a JavaScript browser sniffer to add a 'firefox' class to my HTML does not qualify as clean in my opinion. I would rather like to see something that depends on browser capabilities, much like conditional comments are only 'special' to IE…

TylerH
  • 20,799
  • 66
  • 75
  • 101
avdgaag
  • 41,292
  • 7
  • 29
  • 26

14 Answers14

1429

This solution does not rely on JavaScript being turned on.

@-moz-document url-prefix() {
  h1 {
    color: red;
  }
}
<h1>This should be red in FF</h1>

It's based on yet another Mozilla-specific CSS extension. There's a whole list of these CSS extensions right here: Mozilla CSS Extensions. ⚠ Do note that they are mostly deprecated!

For more information about this specific CSS extension, see this question: What does @-moz-document url-prefix() do?

Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202
  • 26
    What exactly does the url-prefix() mean after the "@-moz-document" ? just curious. – Matt Jul 13 '11 at 16:59
  • 21
    @Matt, that's a way to filter the websites on which that CSS is applied. Another option is to use the `domain()` filter. For example `@-moz-document domain(google.com) {...}` will apply the enclosed CSS rules only on the google.com domain. – Ionuț G. Stan Jul 14 '11 at 08:48
  • 15
    I like how you don't have to create an entirely new CSS document for this like you do for IE. – JD Isaacks Oct 06 '11 at 13:35
  • 8
    @JohnIsaacks You don't need a separate stylesheet for the IE conditional comments. They can be inline. Whether you want to do it that way is another question. – Dylan Nov 18 '11 at 22:36
  • 1
    For those using Razor syntax with asp.net mvc3, the "@" symbol can be escaped by replacing it with "@@". – Andrew Nov 22 '11 at 15:38
  • 1
    Thanks for this, now i have a workaround for the stupid Fieldset borders in FF. – Stefan Sep 04 '12 at 17:13
  • Isn't this considered a CSS hack? I thought CSS hacks were very much not an acceptable solution for more than one reason (not the least of which being not future-proof)? – VoidKing May 02 '13 at 14:09
  • This is a great work around, however adding this to a CSS in VS 2012 gives some issues. The syntax isn't recognised by the schema so pressing CTRL+K, CTRL+D to format appends a semi-colon at the end of my first selector "#nav-main-mega li a" – Leigh Jun 02 '13 at 19:25
  • @Leigh I'm having the same issue with VS 2012 and asked it in a [question](http://stackoverflow.com/questions/17981357/firefox-specific-css-causing-multiple-errors-in-visual-studio). I tried doing what you said in pressing CTRL+K, CTRL+D and gives me the same result. – Abriel Aug 01 '13 at 15:22
  • 14
    It's worth noting that this workaround *no longer works* as of Firefox 59, released March 2018: https://bugzilla.mozilla.org/show_bug.cgi?id=1035091 – Jordan Gray Dec 17 '19 at 17:16
  • 6
    "_no longer works_ as of Firefox 59", but it was _fixed_ in Firefox 61: [https://bugzilla.mozilla.org/show_bug.cgi?id=1446470](bugzilla.mozilla.org/show_bug.cgi?id=1446470) – Goozak Aug 25 '20 at 19:05
  • For what it's worth, this does not work for me on Firefox 89, at least on the Mac. The solution below using `@supports` did work for me, however. – dbeachy1 Jul 30 '21 at 17:08
  • This works perfectly - tried it on FF 96 and Chrome Version 97.0. The rule only applies on FF : ) – Sofía Feb 15 '22 at 14:44
178

Updated(from @Antoine comment)

You can use @supports

@supports (-moz-appearance:none) {
    h1 { color:red; } 
}
<h1>This should be red in FF</h1>

More on @supports here

laaposto
  • 11,835
  • 15
  • 54
  • 71
  • 21
    This is a much nicer solution than @-moz-document url-prefix() example, it also plays nice with SCSS parser whereas the other one didn't. – Alastair Hodgson Dec 14 '15 at 15:40
  • 1
    I'm using Firefox and it's still white, is it because of the version I'm using ? – Antoine Nov 28 '17 at 18:22
  • 3
    @Antoine You are right! It didn't work for latest versions of FF. I updated my answer. It should work now. Thanx for pointing it out! – laaposto Nov 29 '17 at 10:24
  • 2
    Same for me, @JavierC.H. -- this is the only approach that worked for me in Firefox 89, at least on the Mac. – dbeachy1 Jul 30 '21 at 17:09
84

Here is how to tackle three different browsers: IE, FF and Chrome

<style type='text/css'>
/*This will work for chrome */
#categoryBackNextButtons
{
    width:490px;
}
/*This will work for firefox*/
@-moz-document url-prefix() {
    #categoryBackNextButtons{
        width:486px;
    }
}
</style>
<!--[if IE]>
<style type='text/css'>
/*This will work for IE*/
#categoryBackNextButtons
{
    width:486px;
}
</style>
<![endif]-->
Barney
  • 2,355
  • 3
  • 22
  • 37
Waqas Ali Khan
  • 1,317
  • 13
  • 14
  • 69
    If I understand this correctly, the top one isn't chrome, but just specifies the default behavior which you override for Firefox and IE. – Muhd Apr 03 '12 at 22:45
  • 4
    Very useful. As an ex Firefox lover, I'm gutted that I have to do Firefox specific hacks like this but so long as it works I can live with it. – SpaceBeers May 29 '12 at 09:56
  • The suggestion for IE detection does not work if you want to add it into a .css file. You can include stylesheets with it that way in HTML though. If you want to have IE CSS in a CSS file, I recommend looking at here: http://keithclark.co.uk/articles/moving-ie-specific-css-into-media-blocks/media-tests/ – Biepbot Von Stirling Apr 06 '17 at 11:45
16

Here is some browser hacks for targeting only the Firefox browser,

Using selector hacks.

_:-moz-tree-row(hover), .selector {}

JavaScript Hacks

var isFF = !!window.sidebar;

var isFF = 'MozAppearance' in document.documentElement.style;

var isFF = !!navigator.userAgent.match(/firefox/i);

Media Query Hacks

This is gonna work on, Firefox 3.6 and Later

@media screen and (-moz-images-in-menus:0) {}

If you need more information,Please visit browserhacks

Hbirjand
  • 1,945
  • 19
  • 25
  • 2
    Could you elaborate a bit more on "using selector hacks" and on how the example you provided specifically works? Thanks. – Redoman Nov 30 '14 at 11:15
  • 2
    Alright got it myself: basically what it does is hiding the second selector to other browsers which don't understand the first one. In this case only Mozilla understands `_:moz-tree-row(hover)` so it will be the only one to be able to process the `.selector{}` coming after. This specifical hacks *currently* works on all version of Firefox, check http://browserhacks.com/ for more on this. – Redoman Nov 30 '14 at 11:31
  • 1
    I used the Media Query Hack: \@media screen and (-moz-images-in-menus:0) {} This goes nicely with \@media screen and (-webkit-min-device-pixel-ratio:0) and Visual Studio does not throw a warning using it. – Dan Randolph Jun 06 '15 at 01:50
  • 1
    Please note -moz-images-in-menus:0 has been removed in Firefox 52 - https://bugzilla.mozilla.org/show_bug.cgi?id=1302157 – jonathanKingston Oct 11 '16 at 10:53
13

First of all, a disclaimer. I don't really advocate for the solution I present below. The only browser specific CSS I write is for IE (especially IE6), although I wish it wasn't the case.

Now, the solution. You asked it to be elegant so I don't know how elegant is it but it's sure going to target Gecko platforms only.

The trick is only working when JavaScript is enabled and makes use of Mozilla bindings (XBL), which are heavily used internally in Firefox and all other Gecko-based products. For a comparison, this is like the behavior CSS property in IE, but much more powerful.

Three files are involved in my solution:

  1. ff.html: the file to style
  2. ff.xml: the file containg the Gecko bindings
  3. ff.css: Firefox specific styling

ff.html

<!DOCTYPE html>

<html>
<head>
<style type="text/css">
body {
 -moz-binding: url(ff.xml#load-mozilla-css);
}
</style>
</head>
<body>

<h1>This should be red in FF</h1>

</body>
</html>

ff.xml

<?xml version="1.0"?>

<bindings xmlns="http://www.mozilla.org/xbl">
    <binding id="load-mozilla-css">
        <implementation>
            <constructor>
            <![CDATA[
                var link = document.createElement("link");
                    link.setAttribute("rel", "stylesheet");
                    link.setAttribute("type", "text/css");
                    link.setAttribute("href", "ff.css");

                document.getElementsByTagName("head")[0]
                        .appendChild(link);
            ]]>
            </constructor>
        </implementation>
    </binding>
</bindings>

ff.css

h1 {
 color: red;
}

Update: The above solution is not that good. It would be better if instead of appending a new LINK element it will add that "firefox" class on the BODY element. And it's possible, just by replacing the above JS with the following:

this.className += " firefox";

The solution is inspired by Dean Edwards' moz-behaviors.

Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202
12

Using -engine specific rules ensures effective browser targeting.

<style type="text/css">

    //Other browsers
    color : black;


    //Webkit (Chrome, Safari)
    @media screen and (-webkit-min-device-pixel-ratio:0) { 
        color:green;
    }

    //Firefox
    @media screen and (-moz-images-in-menus:0) {
        color:orange;
    }
</style>

//Internet Explorer
<!--[if IE]>
     <style type='text/css'>
        color:blue;
    </style>
<![endif]-->
Rayjax
  • 7,494
  • 11
  • 56
  • 82
8

Now that Firefox Quantum 57 is out with substantial — and potentially breaking — improvements to Gecko collectively known as Stylo or Quantum CSS, you may find yourself in a situation where you have to distinguish between legacy versions of Firefox and Firefox Quantum.

From my answer here:

You can use @supports with a calc(0s) expression in conjunction with @-moz-document to test for Stylo — Gecko does not support time values in calc() expressions but Stylo does:

@-moz-document url-prefix() {
  @supports (animation: calc(0s)) {
    /* Stylo */
  }
}

Here's a proof-of-concept:

body::before {
  content: 'Not Fx';
}

@-moz-document url-prefix() {
  body::before {
    content: 'Fx legacy';
  }

  @supports (animation: calc(0s)) {
    body::before {
      content: 'Fx Quantum';
    }
  }
}

Targeting legacy versions of Firefox is a little tricky — if you're only interested in versions that support @supports, which is Fx 22 and up, @supports not (animation: calc(0s)) is all you need:

@-moz-document url-prefix() {
  @supports not (animation: calc(0s)) {
    /* Gecko */
  }
}

... but if you need to support even older versions, you'll need to make use of the cascade, as demonstrated in the proof-of-concept above.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
8

A variation on your idea is to have a server-side USER-AGENT detector that will figure out what style sheet to attach to the page. This way you can have a firefox.css, ie.css, opera.css, etc.

You can accomplish a similar thing in Javascript itself, although you may not regard it as clean.

I have done a similar thing by having a default.css which includes all common styles and then specific style sheets are added to override, or enhance the defaults.

Anzil khaN
  • 1,974
  • 1
  • 19
  • 30
Kekoa
  • 27,892
  • 14
  • 72
  • 91
  • That does some like a nice and stable approach — thanks — although it still depends on browser sniffing. I'd rather use something that depends on capability, like a Gecko-only CSS rule or something. I do use the same basic approach: default styles and browser-specific add-ons. – avdgaag Jun 04 '09 at 22:13
  • 1
    @avdaag: Capability detection is preferred in most cases, but when you're trying to inject a hack to "fix" a specific rendering engine's bug, then targeting the user agent is, in theory, the optimal solution. You're not discriminating against unknown browsers; and the user-agent field is supposed to tell you what rendering engine the browser is using, so even if a rare Gecko browser comes along, it'll still be given the fix. That said, a lot of browsers now fake their user-agent strings due to inappropriate use of browser-detection. So in practice it might not work out so well. – Lèse majesté Apr 08 '11 at 08:33
3

with -moz prefix

div:-moz-read-only {
  background: green;
}

textarea:-moz-read-write {
  background: green;
}

:-moz-any(div#foo) div.bar {
  background: green;
}

li:-moz-first-node, li:-moz-last-node {
  background: green;
}
Time Killer
  • 693
  • 8
  • 21
3

The only way to do this is via various CSS hacks, which will make your page much more likely to fail on the next browser updates. If anything, it will be LESS safe than using a js-browser sniffer.

Jerod Venema
  • 44,124
  • 5
  • 66
  • 109
2

CSS support can be used from JavaScript.

if (CSS.supports("( -moz-user-select:unset )")) {
    console.log("FIREFOX!!!")
}

https://developer.mozilla.org/en-US/docs/Web/CSS/Mozilla_Extensions

NVRM
  • 11,480
  • 1
  • 88
  • 87
2

How to Apply CSS to Only Firefox

This solution below offers you decent Firefox-only CSS support in a wider range of Firefox browser versions...

@supports (-moz-appearance:button) and (contain:paint) {

  body {
    background: red;
  }

}

-moz-appearance:button was supported in Mozilla/Firefox as early as 2006. But the @supports rule was not supported till 2019 so that would be the earliest Firefox browser supporting this rule. contain:paint excludes Safari browsers from the rule. Internet Explorer and early Trident Edge browsers do not support @supports so also excluded from seeing the CSS rule. No known Chrome browser should support -moz-appearance:button, so excluded.

As always, all my CSS solutions are 100% JavaScript-free :)

Stokely
  • 12,444
  • 2
  • 35
  • 23
1

The following code tends to throw Style lint warnings:

@-moz-document url-prefix() {
    h1 {
        color: red;
    }
}

Instead using

@-moz-document url-prefix('') {
    h1 {
        color: red;
    }
}

Helped me out! Got the solution for style lint warning from here

Kailas
  • 7,350
  • 3
  • 47
  • 63
0

I use this with Google Web Designer to target Firefox

@supports (-moz-appearance:none) {
  .class-name {
        
  }
}
atazmin
  • 4,757
  • 1
  • 32
  • 23