19

Is there a way to detect browser support for background-attachment: fixed?

Edit: Although this feature is widely supported on desktop browsers it is poorly supported on portable devices which I why I would like to be able to detect the feature.

Malcr001
  • 8,179
  • 9
  • 44
  • 57
  • The answers below give you some good details on the complexities, but the following post has a css/html alternative strategy to achieve the same result: http://stackoverflow.com/questions/9779195/does-a-background-attachment-of-fixed-work-in-ios5 – ctrlplusb Mar 05 '15 at 08:32

7 Answers7

7

When you use { background-attachment:fixed } current mobile devices will not display the background image at all! To ensure the image is displayed on all mobile devices, you need to test for support, and if not supported to set the background-attachment property to either 'initial' (i.e. default state) or 'scroll' (which is the default state).

 

The bad news:

It's currently impossible to directly and specifically test for support of fixed backgrounds because mobile browsers will incorrectly report that they do support it. To see this bug for yourself, load this test in a mobile browser:

http://codepen.io/mattthew/pen/PwEqJa

function supportsCSS(value) {
    try {
        var style = document.body.style;
        if (!("backgroundAttachment" in style)) return false;
        var oldValue = style.backgroundAttachment;
        style.backgroundAttachment = "fixed";
        var isSupported = (style.backgroundAttachment === value);
        style.backgroundAttachment = oldValue;
        return isSupported;
    }
    catch (e) {
        return false;
    }
}

var el = document.getElementById('result');
var txt = '<b>This device &amp; broswer supports:</b><br>';
txt += '{ background-attachment:fixed; } : ' + supportsCSS('fixed') + '<br>';
txt +=  { background-attachment:foo; } : ' + supportsCSS('foo');

el.innerHTML = txt;

based on code originally written by: @chao


The limited options:

It is possible to indirectly test for support with multiple methods.

Option 1: Remove fixed background on small screens

This option uses a CSS media query to target smaller screens to overwrite the style on devices with screen widths of 1024px or smaller (devices likely to render fixed backgrounds as invisible). The advantages of this option are: it's very lightweight and only requires a little bit of CSS:

#some_element {
     background-attachment: fixed;
}

@media all and (max-device-width: 1024px) {
     /* 
     overwrite property for devices with 
     screen width of 1024px or smaller  
     */
     #some_element {
          background-attachment: scroll;
     }
}

Unfortunately, there are a small number of tablet brands with screen widths of 1280px and 1366px, which overlap with the smallest desktop screens (sort this list by CSS Height). The safest play is to use a scrolling background for this overlap area so that the background image is guaranteed to display. If you want to play it safe, use max-device-width: 1366px. However, the number of people using these giant tablets is much smaller than the number of people with small screen laptops.

Option 2: test for touch events and mouse events

This option uses JS to test if the browser supports the touch events API, and is therefore more likely than not to be on a touch screen device (a device more likely than not to render fixed backgrounds as invisible). This is the heavy weight option. It requires Modernizr and jQuery:

if(Modernizr.touch) {
  // this browser claims to support touch, so remove fixed background
  $('#some_element').css('background-attachment','scroll');
}

Unfortunately, this option also has a gray area. Some browsers give a false positive and some give a false negative. You could test for a mouse event, such as:

$('body').mousemove(function(event){
  // this device (touch or not) has a mouse, so revert to fixed background
  $('#some_element').css('background-attachment','fixed');
  $('body').unbind('mousemove');
});

However, it's possible that a mouse has been attached to a touch-screen laptop that doesn't support fixed backgrounds, so that code adds risk.

mattthew
  • 528
  • 4
  • 11
  • 1
    Unfortunately, you cannot detect touch efficiently (and nor should you) and Modernizr have dropped support from v3. http://www.stucox.com/blog/you-cant-detect-a-touchscreen/ – Alex Feb 26 '16 at 15:38
2

You might look at document.body.style and make sure that

  • there's a property there called "backgroundAttachment", and
  • you can set it to "fixed", and it retains its value when you do so.

Chrome, FF, Opera, and Safari all ignore attempts to set the property to an invalid value. IE9 throws an exception when you try. So if either one happens, that value definitely isn't supported. (If the browser just blindly sets the value and retains it, then it still might not work. But at that point, you really can't the browser to tell you much anyway.)

function supportsFixedBackground() {
    try {
        var style = document.body.style;
        if (!("backgroundAttachment" in style)) return false;
        var oldValue = style.backgroundAttachment;
        style.backgroundAttachment = "fixed";
        var isSupported = (style.backgroundAttachment === "fixed");
        style.backgroundAttachment = oldValue;
        return isSupported;
    }
    catch (e) {
        return false;
    }
}

I don't bother with IE6 anymore, and don't have another browser handy that doesn't support fixed backgrounds, so i'm unable to test setting "fixed".

cHao
  • 84,970
  • 20
  • 145
  • 172
  • Trying to get this one to work, it always returns false for me. Am I testing the function wrong? all I'm doing is... alert(supportsFixedBackground()); – Malcr001 Jan 02 '13 at 00:14
  • Eh...hold on. i didn't actually test this code, just the setting of the property. Testing now. – cHao Jan 02 '13 at 00:19
  • Odd, it works fine for me in Safari (Mac), Chrome, Opera, FF, and IE9. Like i said, i don't have other browsers to test with. See http://jsfiddle.net/7gjzV/ – cHao Jan 02 '13 at 00:26
  • I tested it in most of those browsers too and I continue to get false. Whats wrong with this test page? [link](http://dev.imagine-that.co.uk/rjm_design/test.html) – Malcr001 Jan 02 '13 at 00:36
  • 1
    Edit: I added $(document).ready(function .. and it returns true now but my android smartphone is still reporting true and yet it makes no attempt at trying to keep the background fixed. – Malcr001 Jan 02 '13 at 00:46
  • 1
    @user971824: If it's returning true even though there's no support, then the browser can't be trusted to tell you what it supports. In that case, i don't know if there's going to be a way other than checking the value of `navigator.appName` and/or `navigator.appVersion` against a list. :P – cHao Jan 02 '13 at 01:14
  • Browser sniffing wont be the best way to solve this issue I'm just going to have to give my mobile site one background that expands/repeats to the bottom. Its a shame I cant add a fixed background for those mobiles that genuinely support it. Thanks anyway you've been a great help. – Malcr001 Jan 02 '13 at 01:58
1

I think I've got the solution for all devices. It's possible to detect clip-support, so I did just that and made a change in the DOM for when clip is supported. If it isn't, it falls back on background-attachment: fixed;

See the code at https://codepen.io/AartdenBraber/pen/gGmdWK

Aart den Braber
  • 864
  • 1
  • 11
  • 23
0

Support for any CSS property value can be detected via following steps:

  1. create a temporary element (e.g. DIV);
  2. set value of its style DOM property (element.style.backgroundAttachment in your case) to value to check (fixed in your case);
  3. compare actual style value with specified string.

Something like this in your case:

var elem = document.createElement('div');
elem.style.backgroundAttachment = 'fixed';
var isSupported = 'fixed' === elem.style.backgroundAttachment;
Marat Tanalin
  • 13,927
  • 1
  • 36
  • 52
  • 1
    Nice idea but its providing me with a lot of false positives on mobile devices. – Malcr001 Jan 01 '13 at 23:59
  • 1
    If `isSupported` in the example is `true`, but the feature itself does not work as expected, then this is not a false positive: the feature is supported, but its implementation just has some specifics. – Marat Tanalin Jan 02 '13 at 00:06
  • 1
    I agree with you that this should simply work, but it doesn't... :/ I don't really get why the browsers would give a false positive and not just 'admit' they can't do it. Then we could just work around it. – Aart den Braber Apr 08 '17 at 11:01
  • See http://codepen.io/AartdenBraber/pen/PprBpB for the false positives... – Aart den Braber Apr 08 '17 at 11:07
  • @AartdenBraber You should be more specific: what exact browser and what exact version gives you a false positive? – Marat Tanalin Apr 08 '17 at 13:53
0

@supports (background-attachment: fixed) will report true because the browser engine interpreted the property and value successfully. Then, mobile webkit decides to bind your background to the same stacking context (same rendering plane) as the element it is applied to for "better performance". (All z-indexes have their own stacking layer, and on desktop browsers, fixed backgrounds get their own layer.)

One could use JS to detect browsers with this rendering pattern, by checking for iPhone iPad iPod & Android in the user agent, which may target mobile browsers that render fixed backgrounds correctly, such as mobile Firefox which is constantly evolving. However, I found a better way in pure CSS:

CSS Only Solution for Mobile Safari & Chrome:

@supports (-webkit-overflow-scrolling: touch) targets all the same versions of mobile webkit that refuse to bind backgrounds to the viewport.

So with that in mind, you can fix your background by default, then append this @supports rule to apply a sort of mobile polyfill:

Example:

body {
 background-image: url('bg.png');
 background-size: cover; background-attachment: fixed;
}

@supports (-webkit-overflow-scrolling: touch) {

 /* Detach problematic background */
 body { background: none !important; }

 /* Insert empty div at bottom of page */
 #lonelyDiv {
  position: fixed; top: 0px; left: 0px; z-index: -1;
  width: 100%; height: 100%;

  /* Using same background with size=cover may be possible in some situations */
  background-image: url('bg.png'); background-size: cover;

  /* Other designs may require a stretchable background...
   or cropped versions for mobile aspect ratios applied after @media (orientation) rules */
  background-image: url('mobile-bg.png'); background-size: 100%;
 }
}
Aaron Gillion
  • 2,227
  • 3
  • 19
  • 31
-4

http://www.w3schools.com/cssref/pr_background-attachment.asp

There are pictures of the major browser icons a little bit down the page. The images aren't greyed out for any of the icons. It says that it is supported in all browsers

Cody Guldner
  • 2,888
  • 1
  • 25
  • 36
  • 5
    You're quoting from the site that claims that IE doesn't support `@font-face` despite having invented the rule. – Niet the Dark Absol Jan 01 '13 at 23:20
  • 1
    its not supported in ie6 and older, just like you said. The page said that – Cody Guldner Jan 01 '13 at 23:25
  • 2
    @CodyGuldner: What he's saying is, you can't really trust what w3schools says about stuff like that. They're rather infamous for having outdated and sometimes outright bad info. You'd have to make sure for yourself, at which point it doesn't particularly matter what the site says. – cHao Jan 01 '13 at 23:27
-4

fixed is supported in all desktop browsers, except IE6 and older.

It is supported by most mobile browsers, but you may see some discrepencies due to viewport handling.

Source

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • 1
    I dont just build websites for desktop browsers though, I'm finding that my android smartphone does not support background-attachment: fixed so I would like to be able to detect the feature. – Malcr001 Jan 01 '13 at 23:27
  • i wouldn't say "most mobile browsers", have a look here: http://www.quirksmode.org/css/backgrounds-borders/mobile.html – Martin Schuhfuß Mar 13 '14 at 15:09