Is it possible to style text tracks (like subtitles and captions) in HTML5 video players?
I already found a way to do so for Chrome:
video::-webkit-media-text-track-container {
// Style the container
}
video::-webkit-media-text-track-background {
// Style the text background
}
video::-webkit-media-text-track-display {
// Style the text itself
}
This seems to confuse Safari a bit. It works, but the rendering is quite buggy.
But more important: How to achieve do this for Firefox and IE?
The only cross-browser solution I have found to date is: Hide the video’s text tracks and use your own.
This will allow you to create your own text nodes, with classes, id’s etc. which can then be styled simply via css.
In order to do so, you would utilize the onenter and onexit methods of the text cues in order to implement your own text nodes.
var video = document.querySelector(‘YOUR_VIDEO_SELECTOR’)
tracks = video.textTracks[0],
tracks.mode = 'hidden', // must occur before cues is retrieved
cues = tracks.cues;
var replaceText = function(text) {
$('WHERE_TEXT_GETS_INSERTED').html(text);
},
showText = function() {
$('WHERE_TEXT_GETS_INSERTED').show();
},
hideText = function() {
$('WHERE_TEXT_GETS_INSERTED').hide();
},
cueEnter = function() {
replaceText(this.text);
showText();
},
cueExit = function() {
hideText();
},
videoLoaded = function(e) {
for (var i in cues) {
var cue = cues[i];
cue.onenter = cueEnter;
cue.onexit = cueExit;
}
},
playVideo = function(e) {
video.play();
};
video.addEventListener('loadedmetadata', videoLoaded);
video.addEventLister('load', playVideo);
video.load();
Use this for Chrome:
video::cue {
// add style here
}
Firefox:
Not yet supported. Open bug to implement ::cue pseudo-element -
https://bugzilla.mozilla.org/show_bug.cgi?id=865395
Edit:
Support for FireFox is available, it works similarly as it does in Chrome and Opera. But support is not yet available for Edge or IE.
I set out to style my captions to have a black background and be positioned below the video for Safari and Chrome. I have achieved success with the following code combined with editing the .vtt file with the following styles. Note you must add the styles to the .vtt file or else in safari your captions will jump around when the video controls (even if they're hidden) would appear:
4
00:00:09.980 --> 00:00:12.640 line:13 position:50% align:middle
size:100%
for just the summer but I ended up staying here.
Styles for chrome and safari captions:
Chrome uses the video::cue background-color and opacity.
video::cue {
opacity: 1;
background-color: black;
font-size: 20px !important;
}
Safari uses -webkit-media-text-track-display-backdrop for it's background color. Note the !important which overrides Safari's inherent styling.
video::-webkit-media-text-track-display-backdrop {
background-color: black !important;
overflow: visible !important;
}
The following webkit-media-text-track-display overflow is allow for more padding around Chrome's caption text:
video::-webkit-media-text-track-display {
overflow: visible !important;
}
Overflow visible is important on the following code for Safari and I'm setting the captions below the video with the transform, which is reliant on a fixed font-size:
video::-webkit-media-text-track-container {
overflow: visible !important;
transform: translateY(30%) !important;
}
EDIT
With some tweaking I ended up using this for my project:
Important: Delete all inline styling from your .VTT file.
Determine if the user is using chrome or safari.
const rootElement = document.getElementById('root');
const M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
rootElement.className += "web";
if(M[1] === 'chrome'){
rootElement.className += " chrome";
} else {
rootElement.className += " safari";
}
Then in a SASS .scss file use the following styles. NOTE: If you're not using SASS you can simply create a class for the video element and nest the corresponding styles.
.chrome {
video::cue {
font-size: 24px;
opacity: 1;
background-color: black;
-webkit-transform: translateY(10%) !important;
transform: translateY(10%) !important;
}
video::-webkit-media-text-track-display {
overflow: visible !important;
-webkit-box-sizing: border-box;
background: black;
padding: 8px;
border-radius: 16px;
}
video::-webkit-media-text-track-container {
overflow: visible !important;
-webkit-transform: translateY(40%) !important;
transform: translateY(40%) !important;
position: relative;
}
}
.safari {
video::cue {
font-size: 24px;
opacity: 1;
background-color: black;
}
video::-webkit-media-text-track-display-backdrop {
background-color: black !important;
overflow: visible !important;
}
video::-webkit-media-text-track-display {
overflow: visible !important;
-webkit-box-sizing: border-box;
}
video::-webkit-media-text-track-container {
overflow: visible !important;
-webkit-transform: translateY(20%) !important;
transform: translateY(20%) !important;
position: absolute;
}
}
This is working for chrome,
video::-webkit-media-text-track-container {
// Style the container
}
video::-webkit-media-text-track-background {
// Style the text background
}
video::-webkit-media-text-track-display {
// Style the text itself
}
you can also get some information from those links.
Link 1
Link 2
html
<video >
<source ref="videoSource">
<track default kind="subtitles" src="xxx" />
</video>
//custom element for showing subtitle
<div ref='subtitleTrackWrapper' v-show='showTextTrack'></div>
javascript
let textTrack = [your video tag].textTracks[0]
textTrack.mode = 'hidden'
textTrack.addEventListener('cuechange', () => {
const cues = textTrack.activeCues;
if(cues.length>0){
this.showTextTrack = true
this.$refs.subtitleTrackWrapper.innerHTML = cues[0].text
}else{
this.showTextTrack = false
}
});
Related
<body>
<video width="500" height="375" controls class="playr_video">
<source type="video/mp4" src="testvideo.mp4" />
<track kind="subtitles" src="testvideo.vtt" srclang="en" />
</video>
</body>
</html>
I have this working but the subtitles have a black background, I would like to remove that and make the subtitles have a small black outline without any background. Any help is appreciated, thanks!
As stated here: enter link description here
The only cross-browser solution I have found to date is: Hide the video’s text tracks and use your own.
This will allow you to create your own text nodes, with classes, id’s etc. which can then be styled simply via css.
In order to do so, you would utilize the onenter and onexit methods of the text cues in order to implement your own text nodes.
var video = document.querySelector(‘YOUR_VIDEO_SELECTOR’)
tracks = video.textTracks[0],
tracks.mode = 'hidden', // must occur before cues is retrieved
cues = tracks.cues;
var replaceText = function(text) {
$('WHERE_TEXT_GETS_INSERTED').html(text);
},
showText = function() {
$('WHERE_TEXT_GETS_INSERTED').show();
},
hideText = function() {
$('WHERE_TEXT_GETS_INSERTED').hide();
},
cueEnter = function() {
replaceText(this.text);
showText();
},
cueExit = function() {
hideText();
},
videoLoaded = function(e) {
for (var i in cues) {
var cue = cues[i];
cue.onenter = cueEnter;
cue.onexit = cueExit;
}
},
playVideo = function(e) {
video.play();
};
video.addEventListener('loadedmetadata', videoLoaded);
video.addEventLister('load', playVideo);
video.load();
Not sure which element this is suppose to target for track**
.{
color: rgba(0,0,0,0) !important;
-webkit-text-fill-color: white; /* Will override color (regardless of order) */
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: black;
}
I set out to style my captions to have a black background and be positioned below the video for Safari and Chrome. I have achieved success with the following code combined with editing the .vtt file with the following styles. Note you must add the styles to the .vtt file or else in safari your captions will jump around when the video controls (even if they're hidden) would appear:
4
00:00:09.980 --> 00:00:12.640 line:13 position:50% align:middle
size:100%
for just the summer but I ended up staying here.
Styles for chrome and safari captions:
Chrome uses the video::cue background-color and opacity.
video::cue {
opacity: 1;
background-color: black;
font-size: 20px !important;
}
Safari uses -webkit-media-text-track-display-backdrop for it's background color. Note the !important which overrides Safari's inherent styling.
video::-webkit-media-text-track-display-backdrop {
background-color: black !important;
overflow: visible !important;
}
The following webkit-media-text-track-display overflow is allow for more padding around Chrome's caption text:
video::-webkit-media-text-track-display {
overflow: visible !important;
}
Overflow visible is important on the following code for Safari and I'm setting the captions below the video with the transform, which is reliant on a fixed font-size:
video::-webkit-media-text-track-container {
overflow: visible !important;
transform: translateY(30%) !important;
}
As answered in the duplicate question, use this css:
video::cue {
background-color: transparent;
text-shadow: #000 1px 1px 3px;
}
I've created a simple church directory in which I edited the CSS to change one of the default Map Markers to one of my own. The issue that I am having is that the Map marker is displayed correctly on Chrome and Safari but not Firefox IE or Edge.
copticchurch-directory.org
Code
/*
Theme Name: Listify Child
Theme URI: http://astoundify.com/themes/listify
Template: listify
Version: 1.0
*/
.job_listing-rating-wrapper,
.map-marker-info .rating,
.single-comment-rating,
.star-rating-wrapper {
display: none !important;
}
.type-job_listing.style-grid .job_listing-entry-footer {
display: none;
}
.ion-information-circled
{
content: url(http://copticchurch-directory.org/wp-content/uploads/2016/08/Map-Marker1.svg);
}
.ion-ios.information-circled
{
content: url(http://copticchurch-directory.org/wp-content/uploads/2016/08/Map-Marker1.svg);
}
.ion.md.information-circled
{
content: url(http://copticchurch-directory.org/wp-content/uploads/2016/08/Map-Marker1.svg);
}
The problem is with the use of the content property on regular elements. Use instead the background property, which will have better cross-browser support.
Change the following:
.ion-information-circled {
content: url(...);
}
Into this:
.map-marker .ion-information-circled::before {
content: "";
background: url(...)
}
https://jsfiddle.net/eyvetdz4/2/
I'm trying to look for an example of code that allows the user to animate a gif on mouseover and pause when mouse out. I've seen many tutorials talking about this but I want a different effect.
I noticed that most gifs "reset" when on mouse out. That is, either the gif is covered with a generic image or the animation reverts back to the start. What I would like to achieve is a more seamless "pause" that allows you to start where you left off without using a placeholder image. Similar to the example on this page:
http://www.valhead.com/2013/03/11/animation-play-state/
Notice how when you put the mouse over the image, the animation just pauses without replacing anything, and resumes otherwise.
I don't know if it's possible with a gif because this example is using basic css shapes, but there has to be some way to pause the gif on mouse out and resume on mouse over without covering the image on a looping animation? If not is there a way to use a movie file that pauses on mouse over and plays where it left off when you put the mouse over it?
Thanks!
EDIT: Thanks to #brbcoding and his genius, this issue was solved! Details on the solution can be found either in the posts below or on his blog post: http://codyhenshaw.com/blog/2013/12/17/faux-animated-gifs-with-css3-keyframes/
So, I thought about it for a bit... You could do something cool like this:
First, break your gif into multiple images, then animate them with css keyframes.
#faux-gif {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
margin: auto;
background-image: url(http://i.imgur.com/E2ee6fI.gif);
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
width: 300px;
height: 300px;
/* animation: giffy 0.5s infinite linear; */
/* no fade between frames */
animation: giffy 0.5s infinite steps(1);
}
#faux-gif:hover {
animation-play-state:paused;
}
#keyframes giffy {
0% { background-image: url('http://i.imgur.com/E2ee6fI.gif'); }
15% { background-image: url('http://i.imgur.com/JIi0uul.gif'); }
30% { background-image: url('http://i.imgur.com/owNGnNN.gif');}
45% { background-image: url('http://i.imgur.com/2Ii6XOz.gif'); }
60% { background-image: url('http://i.imgur.com/ZmQBrQ5.gif'); }
75% { background-image: url('http://i.imgur.com/iAsfHyY.gif'); }
90% { background-image: url('http://i.imgur.com/AJwRblj.gif'); }
100% { background-image: url('http://i.imgur.com/fx5wUNY.gif'); }
}
DEMO
JavaScript Version... Not tested very thoroughly, but this would be the basic idea.
window.onload = function() {
function FauxGif(element, frames, speed) {
this.currentFrame = 0,
this.domElement = element,
this.frames = frames || null,
this.speed = speed || 200;
this.interval;
this.init();
}
FauxGif.prototype = {
init: function() {
// set the first one to the first image
console.log(this.frames[0])
this.domElement.style.backgroundImage = "url(" + this.frames[0] + ")";
},
pause: function() {
clearInterval(this.interval);
},
resume: function() {
var that = this;
that.interval = setInterval(function(){
that.currentFrame < that.frames.length - 1 ? that.currentFrame++ : that.currentFrame = 0;
that.domElement.style.backgroundImage = "url(" + that.frames[that.currentFrame] + ")";
}, this.speed);
}
}
var frames = [
'http://i.imgur.com/E2ee6fI.gif',
'http://i.imgur.com/JIi0uul.gif',
'http://i.imgur.com/owNGnNN.gif',
'http://i.imgur.com/2Ii6XOz.gif',
'http://i.imgur.com/ZmQBrQ5.gif',
'http://i.imgur.com/iAsfHyY.gif',
'http://i.imgur.com/AJwRblj.gif',
'http://i.imgur.com/fx5wUNY.gif'
]
var elem = document.querySelector('#faux-gif'),
gif = new FauxGif(elem, frames);
elem.addEventListener('mouseenter', function(){
gif.resume()
});
elem.addEventListener('mouseleave', function() {
gif.pause();
});
}
DEMO
There is not. Gif images can not "see" the mouse. They are merely images which display. In order to pause an animated gif it requires the swapping of a similar image which is not animated.
That being posted, there are jquery plug ins to animate a sprite consisting of static images. These plug ins would allow the sprites to pause on mouse over
In Chrome for Mac, one can "overscroll" a page (for lack of a better word), as shown in the screenshot below, to see "what's behind", similar to the iPad or iPhone.
I've noticed that some pages have it disabled, like gmail and the "new tab" page.
How can I disable "overscrolling"? Are there other ways in which I can control "overscrolling"?
The accepted solution was not working for me. The only way I got it working while still being able to scroll is:
html {
overflow: hidden;
height: 100%;
}
body {
height: 100%;
overflow: auto;
}
In Chrome 63+, Firefox 59+ and Opera 50+ you can do this in CSS:
body {
overscroll-behavior-y: none;
}
This disables the rubberbanding effect on iOS shown in the screenshot of the question. It however also disables pull-to-refresh, glow effects and scroll chaining.
You can however elect to implement your own effect or functionality upon over-scrolling. If you for instance want to blur the page and add a neat animation:
<style>
body.refreshing #inbox {
filter: blur(1px);
touch-action: none; /* prevent scrolling */
}
body.refreshing .refresher {
transform: translate3d(0,150%,0) scale(1);
z-index: 1;
}
.refresher {
--refresh-width: 55px;
pointer-events: none;
width: var(--refresh-width);
height: var(--refresh-width);
border-radius: 50%;
position: absolute;
transition: all 300ms cubic-bezier(0,0,0.2,1);
will-change: transform, opacity;
...
}
</style>
<div class="refresher">
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
</div>
<section id="inbox"><!-- msgs --></section>
<script>
let _startY;
const inbox = document.querySelector('#inbox');
inbox.addEventListener('touchstart', e => {
_startY = e.touches[0].pageY;
}, {passive: true});
inbox.addEventListener('touchmove', e => {
const y = e.touches[0].pageY;
// Activate custom pull-to-refresh effects when at the top of the container
// and user is scrolling up.
if (document.scrollingElement.scrollTop === 0 && y > _startY &&
!document.body.classList.contains('refreshing')) {
// refresh inbox.
}
}, {passive: true});
</script>
Browser Support
As of this writing Chrome 63+, Firefox 59+ and Opera 50+ support it. Edge publically supported it while Safari is an unknown. Track progress here and current browser compatibility at MDN documentation
More information
Chrome 63 release video
Chrome 63 release post - contains links and details to everything I wrote above.
overscroll-behavior CSS spec
MDN documentation
One way you can prevent this, is using the following CSS:
html, body {
width: 100%;
height: 100%;
overflow: hidden;
}
body > div {
height: 100%;
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
This way the body has never any overflow and won't "bounce" when scrolling at the top and bottom of the page. The container will perfectly scroll its content within. This works in Safari and in Chrome.
Edit
Why the extra <div>-element as a wrapper could be useful: Florian Feldhaus' solution uses slightly less code and works fine too. However, it can have a little quirk, when it comes to content that exceeds the viewport width. In this case the scrollbar at the bottom of the window is moved out of the viewport half way and is hard to recognize/reach. This can be avoided using body { margin: 0; } if suitable. In situation where you can't add this CSS the wrapper element is useful as the scrollbar is always fully visible.
Find a screenshot below:
You can use this code to remove touchmove predefined action:
document.body.addEventListener('touchmove', function(event) {
console.log(event.source);
//if (event.source == document.body)
event.preventDefault();
}, false);
Try this way
body {
height: 100vh;
background-size: cover;
overflow: hidden;
}
html,body {
width: 100%;
height: 100%;
}
body {
position: fixed;
overflow: hidden;
}
position: absolute works for me. I've tested on Chrome 50.0.2661.75 (64-bit) and OSX.
body {
overflow: hidden;
}
// position is important
#element {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
}
Bounce effect cannot be disabled except the height of webpage equals to window.innerHeight, you can let your sub-elements scroll.
html {
overflow: hidden;
}
I have tried to auto resize the image using the CSS property max-width, but it does't work in IE7 and IE8. Is there any way to auto resize the image with pure CSS in IE7 and IE8?
Use width: inherit; to make it work with pure CSS in IE8.
(See responsive-base.css.) Like this:
img {
width: inherit; /* This makes the next two lines work in IE8. */
max-width: 100%; /* Add !important if needed. */
height: auto; /* Add !important if needed. */
}
I'm not sure if that works in IE7—please test it and let us know if you're testing IE7. Before I figured out the width: inherit technique I was using the jQuery below, so you could try it if you really need support down to IE7 and the first technique doesn't work:
<!--[if lt IE 9]><script>
jQuery(function($) {
$('img').each(function(){
// .removeAttr supports SSVs in jQuery 1.7+
$(this).removeAttr('width height');
});
});
</script><![endif]-->
Try something like this:
width: expression(document.body.clientWidth > 800 ? "800px" : "auto" );
/* If page is wider than 800px then set width to 800px, otherwise set to auto */
Source (worth taking a look at)
You need a one-time cached expression for IE 6-7.
IMG {
zoom:expression(
function(t){
t.runtimeStyle.zoom = 1;
var maxW = parseInt(t.currentStyle['max-width'], 10);
var maxH = parseInt(t.currentStyle['max-height'], 10);
if (t.scrollWidth > maxW && t.scrollWidth >= t.scrollHeight) {
t.style.width = maxW;
} else if (t.scrollHeight > maxH) {
t.style.height = maxH;
}
}(this)
);
}
Example: http://kizu.ru/lib/ie/minmax.html
JS source file: http://kizu.ru/lib/ie/ie.js
Author: Roman Komarov
Doesn't IE 7&8 recognise the following:
#my-div img
{
max-width:100%;
_max-width:100%;
}
Most web-developers know that IE has fallen behind in the race for standards and being able to show the latest and greatest. Many CSS2 properties are unsupported. Some of the more useful ones, are properties such as max-width, max-height, min-width and finally min-height.
Try this:
<html>
<style>
p {
border:1px solid red;
width:expression(
document.body.clientWidth > (500/12) *
parseInt(document.body.currentStyle.fontSize)?
"30em":
"auto" );
}
</style>
<body>
<p>
[alot of text]
</p>
Use max-width: 100% with height:auto, plus width:auto for IE8:
img
{
max-width: 100%;
height: auto;
}
/* Media Query to filter IE8 */
#media \0screen
{
img
{
width: auto;
}
}
As you also want support for media queries..You can use the following polyfill to add support for media queries to IE6-IE8
https://github.com/scottjehl/Respond (very small in size, just 1-2kb minified and gzipped)
then use the following css:
#media screen and (min-width: 480px){
img{
max-width: 100%;
height: auto;
}
}
I tested it and working for every browser
img{
height: auto;
max-width: 100%;
}