Giter Club home page Giter Club logo

object-fit-images's Introduction

object-fit-images gzipped size build status npm CDNJS jsDelivr

πŸ—» Polyfill object-fit/object-position on <img>: IE9, IE10, IE11, Edge, Safari, ...

  • Fast and lightweight (demo)
  • No additional elements are created
  • Setup is done via CSS
  • Scaling is taken care by the browser (it uses background-size)
  • srcset support
  • src and srcset properties and attributes keep working: img.src = 'other-image.jpg'

Alternative solutions

Comparison fregante
/object-fit-images🌟
constancecchen
/object-fit-polyfill
tonipinel
/object-fit-polyfill
Browsers IEdge 9-14, Android<5, Safari<10 <- Same "All browsers"
Tags img image video picture img
cover/contain πŸ’š πŸ’š πŸ’š
fill πŸ’š πŸ’š πŸ’š
none πŸ’š πŸ’š πŸ’š
scale-down πŸ’š using {watchMQ:true} πŸ’š πŸ’”
object-position πŸ’š πŸ’š πŸ’”
srcset support πŸ’š Native or picturefill notes πŸ’š πŸ’”
Extra elements πŸ’š No πŸ’” Yes πŸ’” Yes
Settings πŸ’š via CSS πŸ’” via HTML πŸ’” via HTML

Usage

You will need 3 things

  1. one or more <img> elements with src or srcset

    <img class='your-favorite-image' src='image.jpg'>
  2. CSS defining object-fit and a special font-family property to allow IE to read the correct value

    .your-favorite-image {
    	object-fit: contain;
    	font-family: 'object-fit: contain;';
    }

    or, if you also need object-position

    .your-favorite-image {
    	object-fit: cover;
    	object-position: bottom;
    	font-family: 'object-fit: cover; object-position: bottom;';
    }

    To generate the font-family automatically, you can use the PostCSS plugin or the SCSS/SASS/Less mixins.

    If you set the font-family via JavaScript (which must be followed by calling objectFitImages()), make sure to include the quotes in the property.

  3. the activation call before </body>, or on DOM ready

    objectFitImages();
    // if you use jQuery, the code is: $(function () { objectFitImages() });

    This will fix all the images on the page and also all the images added later (auto mode).

    Alternatively, only fix the images you want, once:

    // pass a selector
    objectFitImages('img.some-image');
    // an array/NodeList
    var someImages = document.querySelectorAll('img.some-image');
    objectFitImages(someImages);
    // a single element
    var oneImage = document.querySelector('img.some-image');
    objectFitImages(oneImage);
    // or with jQuery
    var $someImages = $('img.some-image');
    objectFitImages($someImages);

    You can call objectFitImages() on the same elements more than once without issues, for example to manually request an update of the object-fit value.

Apply on resize

You don't need to re-apply it on resize, unless:

In one of those cases, use the watchMQ option:

objectFitImages('img.some-image', {watchMQ: true});
// or objectFitImages(null, {watchMQ: true}); // for the auto mode

Install

Pick your favorite:

<script src="dist/ofi.min.js"></script>
<!-- CDN is also available, but I suggest you concatenate JS files instead -->
<!-- Visit https://cdnjs.com/libraries/object-fit-images -->
npm install --save object-fit-images
var objectFitImages = require('object-fit-images');
import objectFitImages from 'object-fit-images';

API

objectFitImages(images, options)

Both parameters are optional.

parameter description
images Type: string, element, array, NodeList, null
Default: null

The images to fix. More info in the Usage section
options Type: object
Default: {}
Example: {watchMQ:true}

watchMQ Type: boolean
Default: false

This enables the automatic re-fix of the selected images when the window resizes. You only need it in some cases

License

MIT Β© Federico Brigante

object-fit-images's People

Contributors

amaldare93 avatar bfred-it avatar dartess avatar extend1994 avatar fregante avatar gbakernet avatar innocentiv avatar lukasdrgon avatar patricknelson avatar paulradzkov avatar piperchester avatar simonselg avatar skwakman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

object-fit-images's Issues

react.js support

Hello I'd like to use this for a React.js application where i have object-fit and object-position for a spritesheet.

I have my react component programmatically set the style. React will however automagically strip fontFamily:.. from the element. Would it be possible to come around this?

myclass:hover does not work

One use case for object-fit and object-position is to be able to animate the images. One common way to animate is by changing the object-position when hovering the image with the mouse cursor.

This does not work.

.my-image {
	object-position: -358px -15px;
	font-family: 'object-fit: cover;object-position: -358px -15px;';
	height: 95px;
}

	.my-image:hover {
		object-position: -1140px -15px;
		font-family: 'object-fit: cover;object-position: -1140px -15px;';
	}

PhantomJS - Attempting to change access mechanism for an unconfigurable property

Hi there,
Seems that PhantomJs (well, most likely QtWebkit) doesn't like .defineProperty over an already existing property.

Do you foresee any easy way to make the script working without .defineProperty?
I assume this bug is also affecting old Safari versions.

example rendering:

var page = require('webpage').create();

page.open('http://bfred-it.github.io/object-fit-images/demo.html', function() {
  page.evaluate(function() {
    return document.querySelector('button').click();
  });

  global.setTimeout(function() {
    page.render('test.png');
    phantom.exit();
  }, 3000);
});

render:
test

UA:
test

Cheers!

Support picture

Like #2, but could be problematic because <picture> overrides whatever is in <img src>. It might need an additional overriding <source> element to be added and removed while checking.

This could already be working with a <picture> polyfill because it supports changes to the src property (which a polyfill would have to change)

This is only needed where <picture> is supported, but object-fit/object-position isn't, which is Edge 13-14, Safari 9.1, iOS 9.3

The support here could be added by duplicating the entire <picture> element and use that to figure out the current value of currentSrc on resize and could also be a solution to #13

<video> support?

Hey Federico, nice work, keep it up!

I wanted to inquire about <video> support. I have an immediate need for this, and will probably be using Fitie. I realize it's more code, and a wrapper element and you're trying to keep things lean. If video could be supported via an add-on module that would be useful. Thanks for considering.

Breaking other js functions

Hello,

Great script!

Is there anyway of delivering for IE only? It seems to be breaking other scripts I have running on the page.

Thanks, Stephen

Support srcset

Should be simple since it doesn't seem to update on resize, just use currentSrc || src.

This could already be working with a srcset polyfill because it supports changes to the src property (which a polyfill would have to change)

This is only needed where srcset is supported, but object-fit/object-position isn't, which is Edge 12-14, Safari 7.1-9.1, iOS 8-9.3

Change API in v3

Using font-family is not necessary most of the time; the module could become leaner and with less restrictions (e.g. object-fit has to always live with object-position inside font-family) by just storing the values inside background-size and background-position

Example

img {
    object-fit: fill; background-size: 100% 100%;
}
img {
    object-fit: cover; background-size: cover;
    object-position: bottom; background-position: bottom;
}

Table with equivalent values for object-fit

Native For polyfill
object-fit: cover background-size: cover
object-fit: contain background-size: contain
object-fit: fill background-size: 100% 100%
object-fit: none background-size: auto
object-fit: scale-down font-family: 'object-fit: scale-down'

Table with equivalent values for object-position

Native For polyfill
object-position: <any> background-position: <any>

object-position would be pretty straightforward as it's a 1:1 match with background-position

Typeerror

Page loads and after script runs, image disappears.

Console error - ofi.browser.js:
Typeerror: attempting to change access mechanism for an unconfigurable property

Ipad Mini 2
OS: iOS v7
Browser: Safari

Unminified Script Available?

Hi there,

I just wondered if you had an unminified version of the object-fit-images script available? I can't find it in the repo, and for my websites I prefer to use unminified scripts to help with debugging during development, then I concatenate and minify all the javascript into one file for production purposes.

Thanks!

Getting this to work

I've read the docs, but still can't get this to work for IE9. In order to get object-fit:cover to work normally, a height and width of 100% needs to be declared. In IE9, it just distorts. Am I missing something?

<html>
<head>
<script src="ofi.browser.js"></script>
<script>objectFitImages();</script> 

<style>
img.my-image {
object-fit: cover;
height: 100%;
width: 100%;
font-family: 'object-fit: cover';
}
</style>
</head>
<body>
<img class="my-image" src="image.jpg" alt="" />
</body>
</html>

Unable to include into existing uglified/minified code.

I found a workaround for this (just to take the edge off after seeing that subject πŸ‘). Basically my workflow is this:

  • Grunt to compile SASS + JS files
  • JS is minified/uglified (etc) into two main files: head.js and foot.js

My main issue here is that I have one main processor for head.js which manually selects a few files here and there and then concatenates/uglifies a few more and so on, until I have my final header file. I noticed that when I included the existing ofi.browser.js file, it failed with JS errors in the targeted browser (IE). This is because IE couldn't handle this file being mangled 2x's.

However, if I disabled the mangling happening by uglify here (https://github.com/bfred-it/npm-bundler/blob/master/index.js#L60) I ended up with a file I could simply add to my existing project without adding another completely separate step in my already complex workflow just to accommodate one file which cannot handle being uglified 2x's.

My fix would likely be:

  1. Add the option to disable uglify in bfred-npm-bundler
  2. Use this new option in object-fit-images and include a command to build a second version of the file which is not minified (or some workflow which first generates a regular version, then a second uglified version in one command).

What do you think? This would work well for me in the long term since then I can get updates to this module without much hassle (i.e. manually editing your custom packager to disable uglify) and still not have a dramatically modified Grunt workflow.

scale-down doesn't work if the images are shown on hover

Hi,

Please check out my example site at: http://185.48.144.115 in the menu at the top hover over the 'services' link to see the submenu in Safari. It doesn't seem to calculate the images correctly if they are in a hidden element on page load. Any way to work around this? I haven't tested this in IE. I need to use it in Safari for the object-position support.

Thank you

Version number

Hi,

Could you please add the version number of your package in the header comment of the dist files?
I could be easier to update in a website ;)

Thanks for reading.
Jon

Not working with charset="ISO-8859-1"

Hi,
I want to use the polyfill inside a website with charset="ISO-8859-1" meta tag at the document head, but I can't because of the special char you are using for the variable in row 3.
This is the error I get: Uncaught SyntaxError: Unexpected token ILLEGAL (ofi.common-js.js:3).

breaks in IE if element is not present

If passed selector is not present in DOM, ofi triggers an error which stops execution of js in IE.
Documentation should give an advice here or maybe handle it inside ofi.

initial scale-down not applied if image not allready loaded on IE

On IE 11.
Using scale-down.

On document ready, I call objectFitImages(null, {watchMQ:true});
But image scale-down only when I resize the widow a first time.

Workaround: do a second call on a timeout.

    $(document).ready(function ($) {
        // init OFI
        objectFitImages(null, {watchMQ:true});
        // need to be recalled after image loaded to apply first scale down
        setTimeout(objectFitImages, 700);
        setTimeout(objectFitImages, 1200);
        setTimeout(objectFitImages, 2000);
        setTimeout(objectFitImages, 3000);
        setTimeout(objectFitImages, 5000);
    });

It seems that objectFitImages need that images are allready loaded to apply the first scale down.

Incompatible with NivoSlider

Hey there!

First of all: thanks heaps for this lib, saves me days of headaches!

It works 99% on my website, except that it seems to remove the 'src' attribute from images without 'object-fit', at least in a particular case. I use a plugin called MetaSlider (www.metaslider.com) on my Wordpress website, and that stops working on Edge etc when using your lib. I've inspected the element, and as far as I can see there is no 'object-fit' in there (see screengrabs below), so in theory it should be unaffected. Other images on my page do stay untouched, so there might be an edge case here somehow.

I'm good for now, will just use objectFitImages() on pages where I actually need it, instead of globally in the header. Just thought I'd let you know, maybe you spot something in the screengrabs...

Cheers,
Max

<head>
	...
	<!--
	object-fit browser compatibility
	https://github.com/bfred-it/object-fit-images
	-->
	<script src="https://unpkg.com/[email protected]/dist/ofi.browser.js"></script>
</head>

<body>
<script>
    jQuery(function () { objectFitImages() });
</script>
...

Working, without object-fit-images:
image

Src removed, with object-fit-images:
image

Inspect img:
image
...cont...
image

Correct escaping of the url in background-image

According to the CSS level 3 specification:

Note: The special parsing rules for the legacy quotation-mark–less syntax means that parentheses, whitespace characters, single quotes (') and double quotes (") appearing in a URL must be escaped with a backslash, e.g. url(open\(parens), url(close\)parens). Depending on the type of URL, it might also be possible to write these characters as URL-escapes (e.g. url(open%28parens) or url(close%29parens)) as described in [URL]. Alternately, the URL can be quoted as a string, in which case only newlines and the character used to quote the string need to be escaped.

The current implementation in object-fit-images opts for quotation-mark–less syntax, but it only escapes the parentheses. It also uses the replace method of strings with a string the first argument, which will replace only the first occurrence. I propose to switch to the quotation-mark syntax which has simpler escaping rules and use a global regex to ensure that all characters are escaped. So something like the following should work:

(ofi.img.currentSrc || ofi.img.src).replace(/(["\\])/g,"\\$1").replace(/\n/g,"\\n")

I'd be happy to prepare a pull request if it makes it easier for you, provided of course that you agree with the proposed change.

jQuery.clone() before load on IE result in transparent

Running on IE11.

on document ready, I call objectFitImages().
I have a carousel that do a jQuery clone() to have enought card to cycle.

But cloned image have the transparent data:image/gif;base64 as src and background,
instead of the expected image.

Original images fit as expected.

I find that bug seem occurs when image are not allready load,
and workraround with $(document).ready(function ($) { setTimeout(objectFitImages, 500); });

Won't work with lazy loaded images

Hello,
I want to use this polifill together with https://github.com/aFarkas/lazysizes which I use to lazy load images and https://github.com/scottjehl/picturefill for the srcset polyfill.
My yes case is the following: I have a carousel with a srcset on the img tag. By default every image in the carousel has an inline placeholder image (base64 gif) The first image in the carousel loads correctly and this library does the job fine. For all the other images in the carousel I get the placeholder images instead.

Image paths containing parentheses not handled

Hi! It appears that image filenames/paths which contain parentheses are not handled--IE ends up replacing the image on screen with a blank background.

Adding quotes to line 45 in index.js fixed the problem in our case. At the time of this writing, line 45 is:

el.style.backgroundImage = 'url(' + src + ')';

Cheers and thanks for writing this!

Please add an unminified version in /dist

I know that there is a raw version at index.js - but it's unwrapped.
I have a workflow that pulls down all libs with raw github URLs, then bundle all libs together in one single libs.js, and then minify that libs.js myself.

Demo broken in IE11

Testing in IE11 on Windows 7 in BrowserStack. Haven't taken a hard look yet, but the debugger's saying s["object-fit"] is returning null.

Here's some quick screenshots and a screencast:

Screenshot from BrowserStack

Screenshot from BrowserStack - Error

Can you distribute a non-minified dist release?

We're trying to use ofi.browser.js with an existing Rails project, but the built-in asset pipeline wants to re-minify all JS files, and unfortunately there seems to be some incompatibilities with our existing JS codebase and ofi.browser.js, which clobbers a function name in ofi.browser.js and throws a runtime exception.

With a non-minified dist .js, we can just let the Rails asset pipeline handle the minification process and hopefully avoid this issue.

Cannot use jQuery object as parameter

Hi. I cannot use jQuery object as parameter of function objectFitImages(), like you have written down in your example in documentation:
// or with jQuery
var $someImages = $('img.some-image');
objectFitImages($someImages);

JS error in console shows up. I have tested it in your DEMO. I have tried a different versions of jQuery, not helped. Thanx.

Unable to get property ... of undefined or null reference

In IE11, I'm getting Unable to get property 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' of undefined or null reference
on this section:
for (var n = 0; n < e.length; n++) { e[n][t] = e[n][t] || r; /* n is 0, e[n] is undefined, t is 'data:image...' */ u(e[n]); }

I include it as <script type="text/javascript" src="http://mysite.dev/wp-content/themes/mytheme/js/ofi.browser.js?ver=20160603"></script>
and call it as jQuery(objectFitImages);

Fix makes image larger than it should be

I have a two column layout with text on the left and an image on the right. The image is supposed to cover the whole second column, which should be as tall as it needs to be to fit the text. In browsers with native support for object-fit this works fine, but when I apply OFI, the image becomes taller than it needs to be. As a result, the text column gets additional space at the bottom that it shouldn't have and the image gets cropped more than necessary. See https://jsfiddle.net/ynrsmoaa/.

Conflict with flickity

I'm using flickity in my project and it breaks this polyfill for ie edge 14. Didn't test in anything else, but I'm sure it's the same story.

No console errors. Just breaks it silently.

Not sure if I should be posting here or over on flickity's issues. Sorry if I'm posting in the wrong place.

I was trying to read the code for this polyfill, but I don't see an unminified version here and can't wrap my head around the minified code. And for figuring out flickity...it's like 4,000 lines long so would rather just try and tweak the smaller script if possible.

Any ideas on how to possible get it working?

Thanks

Callback support

Is it possible to add support for passing a callback function to fire after each image is changed? I'm hiding all images using object-fit in non-supported browsers, with opacity 0 in CSS, and manually set the opacity to 1 after running the script - which I would like to do in the callback.

Changing to `fill` after some other value will fail

This will fail when making the window bigger because fill currently skips any processing, including the necessary "reset", which should now be set with background-size: 100% 100%

                            img { object-fit: fill }
@media (max-width: 500px) { img { object-fit: contain } }

Edge / IE console error: Function Expected

I'm seeing this error on Edge, IE11 and IE10.
Seeing 'Function Expected' in the console.
The CSS is implemented with the following:

.image {
  object-fit: cover;
  object-position: center;
  font-family: 'object-fit: cover; object-position: center;'
}

Calling Object Fit in JQuery as follows:

jQuery(function($) {
  objectFitImages();
});

Why this character ?

Please, why?

const ΰ²  = 'data:image/gif;base64,R0lGODlhAQABAIAAAP

Cause issue on servers who's deliver it without UTF8

Can you change it with a simple character ?

Thank you

This plugin is awesome, it really made my day!
God bless you, man! ❀️ ❀️ ❀️

Non minified code in Github

Hello,

I have a problem when I include the library in my Gulp workflow.
"Uglify" removes a function from your code.

Can you added the non minified code in Github?

Thank you

Cannot override with CSS alone

Hi! It would be extremely useful to be able to use this polyfill on elements, but also have the ability to override it at certain breakpoints using CSS only.

For example, I often want an element to have object-fit: contain on mobile views, but then at my large breakpoint I want to override it with object-fit: none. Because this plugin adds a background image in IE to mimic the object-fit functionality, it cannot later be overriden with only CSS.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.