{"id":17920949,"url":"https://github.com/davidanson/live-photo-web","last_synced_at":"2026-03-08T04:31:31.621Z","repository":{"id":66112530,"uuid":"46398328","full_name":"DavidAnson/live-photo-web","owner":"DavidAnson","description":"Live Photos via Web Components","archived":false,"fork":false,"pushed_at":"2019-08-11T23:56:52.000Z","size":5719,"stargazers_count":22,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-01-31T20:41:46.342Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DavidAnson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-18T05:53:29.000Z","updated_at":"2025-03-17T15:14:04.000Z","dependencies_parsed_at":"2023-04-08T23:46:37.381Z","dependency_job_id":null,"html_url":"https://github.com/DavidAnson/live-photo-web","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DavidAnson/live-photo-web","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidAnson%2Flive-photo-web","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidAnson%2Flive-photo-web/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidAnson%2Flive-photo-web/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidAnson%2Flive-photo-web/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DavidAnson","download_url":"https://codeload.github.com/DavidAnson/live-photo-web/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidAnson%2Flive-photo-web/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30245213,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T00:58:18.660Z","status":"online","status_checked_at":"2026-03-08T02:00:06.215Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-28T20:29:47.112Z","updated_at":"2026-03-08T04:31:31.600Z","avatar_url":"https://github.com/DavidAnson.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# live-photo-web\n\nApple introduced [Live Photos](https://www.apple.com/ios/photos/) with iOS 9, a\nfeature that automatically associates a short video with every picture that's\ntaken. I was skeptical at first, wondering how relevant this would be for static\ncontent; and it turns out not to be all that compelling for some kinds of photos.\nBut for dynamic scenes or people in motion, the video can add some really\ninteresting context!\n\nLive Photos on iOS are (naturally) smooth and easy to use. I wondered what it\nmight be like to bring a similar experience to the web. I'd also been looking\nfor a reason to explore [Web Components](https://en.wikipedia.org/wiki/Web_Components).\nAnd so `live-photo-web` was born!\n\n## Demo\n\n[Click here for a simple demonstration of the techniques described below.](https://dlaa.me/Samples/live-photo-web/)\n\n## live-photo-image\n\nAn easy way to implement the Live Photo effect is to start with a standard\n[`img` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img)\nand swap out it's `src` property with an\n[animated `gif`](https://en.wikipedia.org/wiki/GIF#Animated_GIF) when the user\ntouches the image or hovers the mouse over it. This is easy to do with a bit of\nJavaScript and some code to attach the event handlers - though it's nice to\npackage everything up for reuse. Fortunately, there's an emerging standard that\nenables just that: Web Components. And while browser support for web components\nis [not yet universal](http://caniuse.com/#feat=custom-elements), a handy\npolyfill exists thanks to [WebComponents.org](http://webcomponents.org/). It\nends up being straightforward to write a simple extension to the `img` element\nthat listens to the `mouseenter`, `mouseleave`, `touchstart`, `touchend`, and\n`touchcancel` events to implement the desired behavior. Using it is easy; just\ndecorate an existing `img` element with the `is` syntax and make sure a `gif`\nimage of the same name exists alongside the original `src` image.\n\nHere's what it looks like in practice:\n\n```html\n\u003cimg is=\"live-photo-image\" src=\"sample.jpg\"/\u003e\n```\n\n*See [`live-photo-image.js`](live-photo-image.js) for the complete implementation.*\n\n`gif` images are convenient because they're natively supported by the `img` tag\nin all browsers, automatically play themselves, and automatically loop. However,\nthe `gif` format is poorly suited to storing photo-realistic movies, so file\nsize can be very large (5.19 MB in the example). An (optional) enhancement is\nto have the browser prefetch the `gif` image after loading the page so it will\nalready be cached by the time it's needed. The\n[`link`/`rel`/`prefetch` tag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Link_prefetching_FAQ)\nis ideal for this and looks like the following:\n\n```html\n\u003clink rel=\"prefetch\" href=\"sample.gif\"/\u003e\n```\n\n## live-photo-element\n\nEnhancing an `img` element is simple enough, but creating a dedicated Live\nPhoto element offers even more possibilities. In particular, instead of swapping\nout the `src` to show a `gif`, the code can swap out the entire `img` for a\n[`video` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video)\nto get better quality, much smaller file size - and sound! Add the same\nmouse/touch logic as above, drop an `mp4` video alongside the original `src`\nimage, update the HTML, and you end up with a much richer experience.\n\nHere's what it looks like in practice:\n\n```html\n\u003clive-photo-element src=\"sample.jpg\"\u003e\u003c/live-photo-element\u003e\n```\n\n*See [`live-photo-element.js`](live-photo-element.js) for the complete implementation.*\n\nUnfortunately, there are two drawbacks with this approach. The first is that\n`video` and `mp4` are not as universally supported as `gif`, so there are some\nbrowsers where things don't work smoothly (or possibly at all). The second\nis that the format for Live Photo movies, `mov`, is not natively supported by\nall platforms (notably Windows), so it's a good idea to transcode the `mov` to\na more popular format like `mp4`. On the plus side, transcoding is a good\nopportunity to resize the movie to fit the target scenario - leading to a very\ncompact file size (just 329 KB in the example).\n\n## Thanks\n\n- [WebComponents.org](http://webcomponents.org/)\n- [LiveToGIF for iOS](https://david-smith.org/blog/2015/11/03/introducing-livetogif/)\n- [Lively for iOS](http://lively.tinywhale.net/)\n- [HandBrake](https://handbrake.fr/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidanson%2Flive-photo-web","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidanson%2Flive-photo-web","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidanson%2Flive-photo-web/lists"}