Youtube Video Header Background - html

I'm trying to create a few website templates to help me improve my front end development skills, as I'm currently far better at rear end work.
I'm trying to somewhat replicate the style of my own website (https://thomas-smyth.co.uk/), which is a simple Bootstrap template. However, instead of using a static photo in the header, I want to replace it with a Youtube video. I began by cutting down the template used in my website and have stripped it down to as little as I think I can get it without breaking the header.
I have found a few pieces of code around the place to show how to set a Youtube video as background of the overall page, but not the background for specific sections of the page. How can I do this? Note - It has to be streamed from YouTube as my hosts don't allow me to host video's on their servers.
My current code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<title>Group Name | Home</title>
<!-- Bootstrap 3.3.6 -->
<link rel="stylesheet" href="dist/bootstrap/css/bootstrap.min.css">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
<!-- Ionicons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
<!-- Custom -->
<link rel="stylesheet" href="dist/css/mainstyle.css">
</head>
<body>
<header>
<div class="header-content">
<div class="header-content-inner">
<h1>This is going once vid is done.</h1>
</div>
</div>
</header>
<section class="bg-primary">
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 text-center">
<h2 class="section-heading">Placeholder!</h2>
<p>I should have found a witty comment to put here, but I'm just gonna put "Placeholder" instead.</p>
</div>
</div>
</div>
</section>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="dist/bootstrap/js/bootstrap.min.js"></script>
<script src="dist/js/mainscript.js"></script>
</body>
</html>
CSS
html,
body {
height: 100%;
width: 100%;
}
body {
font-family: 'Merriweather', 'Helvetica Neue', Arial, sans-serif;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
}
p {
font-size: 16px;
line-height: 1.5;
margin-bottom: 20px;
}
.bg-primary {
background-color: #F05F40;
}
section {
padding: 100px 0;
}
.no-padding {
padding: 0;
}
header {
position: relative;
width: 100%;
min-height: auto;
background-image: url('../img/header.jpg');
background-position: 0% 80%;
-webkit-background-size: cover;
-moz-background-size: cover;
background-size: cover;
-o-background-size: cover;
text-align: center;
color: white;
}
header .header-content {
position: relative;
text-align: center;
padding: 100px 15px 100px;
width: 100%;
}
header .header-content .header-content-inner h1 {
font-weight: 700;
text-transform: uppercase;
margin-top: 0;
margin-bottom: 0;
font-size: 30px;
}
#media (min-width: 768px) {
header {
min-height: 100%;
}
header .header-content {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
padding: 0 50px;
}
header .header-content .header-content-inner {
max-width: 1000px;
margin-left: auto;
margin-right: auto;
}
header .header-content .header-content-inner h1 {
font-size: 50px;
}
}
.section-heading {
margin-top: 0;
}
::-moz-selection {
color: white;
text-shadow: none;
background: #222222;
}
::selection {
color: white;
text-shadow: none;
background: #222222;
}
img::selection {
color: white;
background: transparent;
}
img::-moz-selection {
color: white;
background: transparent;
}
body {
webkit-tap-highlight-color: #222222;
}
Best I have so far (does whole page's background)
<div class="video-background">
<div class="video-foreground">
<iframe src="https://www.youtube.com/embed/W0LHTWG-UmQ?controls=0&showinfo=0&rel=0&autoplay=1&loop=1&playlist=W0LHTWG-UmQ" frameborder="0" allowfullscreen></iframe>
</div>
</div>
CSS
* { box-sizing: border-box; }
.video-background {
background: #000;
position: fixed;
top: 0; right: 0; bottom: 0; left: 0;
z-index: -99;
}
.video-foreground,
.video-background iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
#media (min-aspect-ratio: 16/9) {
.video-foreground { height: 300%; top: -100%; }
}
#media (max-aspect-ratio: 16/9) {
.video-foreground { width: 300%; left: -100%; }
}

I've created a simple example with Youtube video background using direct links to video stream (JS/CSS only solution). Feel free to check it on JSfiddle. Also, you can update public Google Image proxy URL to any public or your own CORS proxy.
var vid = "FUUw3zNTXH8",
streams,
video_tag = document.getElementById("video");
fetch("https://images" + ~~(Math.random() * 33) + "-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=" + encodeURIComponent("https://www.youtube.com/watch?hl=en&v=" + vid)).then(response => response.text()).then(function(data) {
if (data) {
streams = parse_youtube_meta(data);
video_tag.src = streams['hls'] || streams['720pna'] || streams['480pna'] || streams['720p'] || streams['480p'] || streams['360p'] || streams['240p'] || streams['144p'];
} else {
alert('Youtube API Error');
}
});
function parse_youtube_meta(rawdata) {
var regex = /(?:ytplayer\.config\s*=\s*|ytInitialPlayerResponse\s?=\s?)(.+?)(?:;var|;\(function|\)?;\s*if|;\s*if|;\s*ytplayer\.|;\s*<\/script)/gmsu;
rawdata = rawdata.split('window.getPageData')[0];
rawdata = rawdata.replace('ytInitialPlayerResponse = null', '');
rawdata = rawdata.replace('ytInitialPlayerResponse=window.ytInitialPlayerResponse', '');
rawdata = rawdata.replace('ytplayer.config={args:{raw_player_response:ytInitialPlayerResponse}};', '');
var matches = regex.exec(rawdata);
var data = matches && matches.length > 1 ? JSON.parse(matches[1]) : false;
console.log(data);
var streams = [],
result = {};
if (data.streamingData && data.streamingData.adaptiveFormats) {
streams = streams.concat(data.streamingData.adaptiveFormats);
}
if (data.streamingData && data.streamingData.formats) {
streams = streams.concat(data.streamingData.formats);
}
streams.forEach(function(stream, n) {
var itag = stream.itag * 1,
quality = false,
itag_map = {
18: '360p',
22: '720p',
37: '1080p',
38: '3072p',
82: '360p3d',
83: '480p3d',
84: '720p3d',
85: '1080p3d',
133: '240pna',
134: '360pna',
135: '480pna',
136: '720pna',
137: '1080pna',
264: '1440pna',
298: '720p60',
299: '1080p60na',
160: '144pna',
139: "48kbps",
140: "128kbps",
141: "256kbps"
};
//if (stream.type.indexOf('o/mp4') > 0) console.log(stream);
if (itag_map[itag]) result[itag_map[itag]] = stream.url;
});
if (data.streamingData && data.streamingData.hlsManifestUrl) {
result['hls'] = data.streamingData.hlsManifestUrl;
}
return result;
};
html, body {
height: 100%;
min-height: 100%;
background: #444;
overflow: hidden;
}
video {
width: 100%;
height: 100%;
object-fit: cover;
}
<video loop muted autoplay playsinline id="video"></video>

I found here a tutorial that explains how to set a video as a background of your page. This tutorial shows how to make the video as a fullscreen background and a background for only a specific page like you want.
You need to set your Html and CSS part to achieve this kind of background. The tutorial page includes some sample code that you can copy.
Hope it helps you.

Thanks to the above, I actually came up with a different method when the old one died out. Maybe not as good as the above, but it works for me. This is made into a WP Plugin and the user sets the height and a few other options like Video ID, mute and volume. Also using YouTube API.
Can see it here at the top of my website: https://neotropicworks.com/
// Output from plugin onto page using 'wp_add_inline_script' to JS file below
var video_id = "qnTsIVYxYkc",video_mute = true,video_volume = 50;
// JS file
var player;
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
player = new YT.Player('youtube-header-player', {
videoId: video_id,
playerVars: {
playlist: video_id,
loop: 1
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
event.target.playVideo();
if(video_mute){
player.mute();
} else {
player.setVolume(video_volume);
}
}
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
player.playVideo();
}
}
In a stylesheet
.video-wrapper{width: 100%;overflow: hidden;position: relative;}
.video-container {position: absolute;width: auto;top: -50%;left: 0;right: 0;bottom: -50%;}
.video-bg {background: none;position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1;}
.video-bg .video-fg,.video-bg iframe,.video-bg video {position: absolute;top: 0;left: 0 !important;width: 100% !important;height: 100%;}
Below is generated output from user on the height they want. They set sizes for the different devices, window sizes for better control.
.video-wrapper{height: 400px;}
.video-container {height: 800px;}
#media (min-width: 768px) and (max-width: 991px) {
.video-wrapper{height: 300px;}
.video-container {height: 600px;}
}
#media (max-width:767px) {
.video-wrapper{height: 200px;}
.video-container {height: 400px;}
}
The HTML
<div class="video-wrapper">
<div class="video-container">
<div class="video-bg">
<div class="video-fg" id="youtube-header-player"></div>
</div>
</div>
</div>

Just sharing a simple jQuery plugin I've made, to make your lives easier.
You only need to select an element with a data-youtube attribute containing a youtube link or ID only. Everything else is done for you by the plugin, including embed api script injection and CSS.
Here is a quick usage sample. You can see it in action here.
<div id="ytbg" data-youtube="https://www.youtube.com/watch?v=eEpEeyqGlxA"></div>
<script type="text/javascript">
jQuery(document).ready(function() {
$('[data-youtube]').youtube_background();
});
</script>
Code on GitHub.

Related

Dynamic UL items not displaying side by side

I am attempting to create a horizontal scroll of a ul populated by an ajax call to an xml document. As constituted, the content will scroll but the list items are stacked rather than side by side. Research suggests that I can achieve the desired result with some simple css. However, I have been unable to successfully make this happen...
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Content-Script-Type" content="text/javascript">
<meta name="Content-Style-Type" content="text/css">
<link href="css/wneRSS.css" rel="stylesheet">
<script src="js/jquery.min.js"></script>
</head>
<body>
<div id="rss">
<div class="list"><ul class="feeder"></ul></div>
</div>
</body>
<script>
$(document).ready(function(){
$.ajax({
type: "GET",
url: "XMLSource",
dataType: "xml",
success: function(xml){
$(xml).find('row').each(function(){
var sfirst = $(this).find('First').text();
var slast = $(this).find('Last').text();
var scity = $(this).find('PermanentCity').text();
var sstate = $(this).find('PermanentRegion').text();
$("<li></li>").html(sfirst + " " + slast + " - " + scity + ", " + sstate).appendTo("#rss ul");
});
},
error: function() {
alert("An error occurred while processing XML file.");
}
});
});
</script>
</html>
CSS:
body {
margin: 0;
padding: 0;
background-color: #373737;
color: white;
font-family: sans-serif;
overflow: hidden;
}
#rss {
width: 1920px;
height: 82px;
margin:0px;
}
.list ul {
padding: 0;
margin: 0;
border: 0;
float: left;
display: inline;
width: auto;
}
.list ul li {
float: left;
margin: 0;
padding: 0;
border: 0;
display: inline;
}
.feeder {
font-size: 40px;
line-height: 82px;
-moz-transform:translateX(100%);
-webkit-transform:translateX(100%);
transform:translateX(100%);
animation: scroller 60s linear infinite;
}
#keyframes scroller {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(-100%);
}
}
Added width=auto to the container solved the problem.
Your container may not be wide enough to accommodate your list items. You need to nest the unordered list elements in a container wide enough that they do not break.

How to create a box around around controls in webprgramming

I have a few controls that I am attempting to encapsulate on my webpage. I have tried a few different methods on encapsulating my controls and they have not succeeded. I tried using a div and this did not work too well and I have also tried this post:
Create a group box around certain controls on a web form using CSS
What is happening is that a box is being created but it is at the top of my webpage instead of around the controls.
I would like to create a grey box similar to the ones found on this webpage:
https://img.labnol.org/di/trigger1.png
Below, I am attaching a copy of the CSS and HTML code that I am using in order to create my form. The form is a simple file upload form that I tweaked from an example. I am using this on my own, personal website.
Here is the HTML:
<!DOCTYPE html>
<html>
<head>
<script>
/* Script written by Adam Khoury # DevelopPHP.com */
/* Video Tutorial: http://www.youtube.com/watch?v=EraNFJiY0Eg */
function _(el){
return document.getElementById(el);
}
function uploadFile(){
var file = _("file1").files[0];
// alert(file.name+" | "+file.size+" | "+file.type);
var formdata = new FormData();
formdata.append("file1", file);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "file_upload_parser.php");
ajax.send(formdata);
}
function progressHandler(event){
//_("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
var percent = (event.loaded / event.total) * 100;
_("progressBar").value = Math.round(percent);
_("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
}
function completeHandler(event){
_("status").innerHTML = event.target.responseText;
_("progressBar").value = 0;
document.getElementById('p1').innerHTML = "Drag your file here or click in this area.";
}
function errorHandler(event){
_("status").innerHTML = "Upload Failed";
}
function abortHandler(event){
_("status").innerHTML = "Upload Aborted";
}
function changeText()
{
document.getElementById('p1').innerHTML = "1 file selected";
}
</script>
<link rel="stylesheet" href="test.css">
</head>
<body>
<h2>Upload</h2>
<fieldset>
<legend>Group 1</legend>
<form id="upload_form" enctype="multipart/form-data" method="post">
<input type="file" name="file1" id="file1"><br>
<p id="p1">Drag your file here or click in this area.</p>
<input type="button" value="Upload File" onclick="uploadFile()">
<progress id="progressBar" value="0" max="100" style="width:508px; margin-left: -4px; margin-top: 10px;"></progress>
<h3 id="status"></h3>
<p id="loaded_n_total"></p>
</form>
</fieldset>
<script>
// self executing function here
(function() {
document.getElementById('upload_form')[0].onchange = changeText;
})();
</script>
</body>
</html>
Here is the CSS (which is referred to in the html as test.css):
body{
background: rgba(0,0,0,0.0);
}
form{
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -250px;
width: 500px;
height: 200px;
border: 4px dashed #0D0D0D;
}
form p{
width: 100%;
height: 100%;
text-align: center;
line-height: 140px;
color: #0D0D0D;
font-family: Arial;
}
h2{
text-align: center;
}
form input[type="file"]{
position: absolute;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
outline: none;
opacity: 0;
}
form input[type="button"]{
margin: 0;
color: #fff;
background: #16a085;
border: none;
width: 508px;
height: 35px;
margin-top: -20px;
margin-left: -4px;
border-radius: 4px;
border-bottom: 4px solid #117A60;
transition: all .2s ease;
outline: none;
}
form input[type="button"]:hover{
background: #149174;
color: #0C5645;
}
form input[type="button"]:active{
border:0;
}
form progressBar{
text-align: center;
}
Coming back to the HTML, the fieldset tags are placed around the controls that I am attempting to encapsulate. I left them there so that anyone can see the main issue that I am running into.
I apologize but I am very new to web programming. Any help will be greatly appreciated, thank you.
Note: how the box is created doesn't really matter to me. I would expect that the box is created in HTML and then I can style it using CSS.
The structure of your HTML is fine, but the position: absolute properties in your CSS are clashing with the fieldset.
Since <fieldset> is wrapping all your controls, I would suggeset giving it a fixed width and height and position your child elements based on that, i.e. use width: 100% for your children and give all of them the same margin so they align nicely. Also make sure you either edit your #progressBar style in the markup.
Here's a snippet with the changes I just mentioned:
body {
background: rgba(0, 0, 0, 0.0);
}
fieldset {
width: 508px;
height: 270px;
/* fixed width and height*/
margin: 13vh auto;
}
#p1 {
border: 4px dashed #0D0D0D;
/* modified the actual text box instead of the entire form */
width: 508px;
height: 140px;
line-height: 140px;
margin-top: 0px;
}
form p {
text-align: center;
color: #0D0D0D;
font-family: Arial;
}
h2 {
text-align: center;
}
form input[type="file"] {
position: absolute;
margin: 0;
outline: none;
width: 508px;
height: 140px;
margin: 22px 4px;
opacity: 1;
background-color: orange;
/* Last two properties are a visual representation. Delete background-color and set opacity to 0 */
}
form input[type="button"] {
margin: 0;
color: #fff;
background: #16a085;
border: none;
width: 100%;
/* width relative to parent fieldset */
height: 35px;
margin-top: -20px;
border-radius: 4px;
border-bottom: 4px solid #117A60;
transition: all .2s ease;
outline: none;
}
form input[type="button"]:hover {
background: #149174;
color: #0C5645;
}
form input[type="button"]:active {
border: 0;
}
form progressBar {
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<script>
/* Script written by Adam Khoury # DevelopPHP.com */
/* Video Tutorial: http://www.youtube.com/watch?v=EraNFJiY0Eg */
function _(el) {
return document.getElementById(el);
}
function uploadFile() {
var file = _("file1").files[0];
// alert(file.name+" | "+file.size+" | "+file.type);
var formdata = new FormData();
formdata.append("file1", file);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "file_upload_parser.php");
ajax.send(formdata);
}
function progressHandler(event) {
//_("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
var percent = (event.loaded / event.total) * 100;
_("progressBar").value = Math.round(percent);
_("status").innerHTML = Math.round(percent) + "% uploaded... please wait";
}
function completeHandler(event) {
_("status").innerHTML = event.target.responseText;
_("progressBar").value = 0;
document.getElementById('p1').innerHTML = "Drag your file here or click in this area.";
}
function errorHandler(event) {
_("status").innerHTML = "Upload Failed";
}
function abortHandler(event) {
_("status").innerHTML = "Upload Aborted";
}
function changeText() {
document.getElementById('p1').innerHTML = "1 file selected";
}
</script>
<link rel="stylesheet" href="test.css">
</head>
<body>
<h2>Upload</h2>
<fieldset>
<legend>Group 1</legend>
<form id="upload_form" enctype="multipart/form-data" method="post">
<input type="file" name="file1" id="file1"><br>
<p id="p1">Drag your file here or click in this area.</p>
<input type="button" value="Upload File" onclick="uploadFile()">
<!-- changed progressBar style -->
<progress id="progressBar" value="0" max="100" style="width:100%; margin-top: 10px;"></progress>
<h3 id="status"></h3>
<p id="loaded_n_total"></p>
</form>
</fieldset>
<script>
// self executing function here
(function() {
document.getElementById('upload_form')[0].onchange = changeText;
})();
</script>
</body>
</html>
Hope it helps!

Appending Text to Div Extends Div Beyond Initial CSS Grid

I've created a basic CSS Grid and had everything positioned where I wanted it. When I run my JS (appends info from an API call to a div), the div's dimension push beyond the borders of the viewport. Is there a way to prevent the overall body element from changing and just have the div dynamically increase height?
pics: https://imgur.com/a/wJAcW
I've tried so many different things and can't seem to figure this out. My fallback will be to just overwrite the div rather than append to it. Code is below.
//Set initial latitute and longitude variables, to be used later
var lat = 0;
var long = 0;
//Google Geocode API to find the latitude and longitude of the txtAddress
$("#submit").on("click", function() {
var userInput = $("#txtAddress").val();
//trim the user input to the form needed for the api
var userSearchTerm = userInput.split(' ').join('+');
//call the google geocode api
var queryURLGeocode = "https://maps.googleapis.com/maps/api/geocode/json?address=" + userSearchTerm + "&key=AIzaSyCSAYHZn9fz13c3bsl_RcS13HJu8wDJXCU"
$.ajax({
url: queryURLGeocode,
method: "GET"
})
.done(function(response) {
//Set latitude and longitude from the returned object
lat = response.results[0].geometry.location.lat;
//limit decimal points to 4 (xx.xxxx) - form needed for hiking api
lat = lat.toFixed(4);
long = response.results[0].geometry.location.lng;
long = long.toFixed(4);
//Call the hiking project api
var queryURL = "https://www.hikingproject.com/data/get-trails?lat=" + lat + "&lon=" + long + "&maxDistance=10&key=200206461-4fa8ac1aa85295888ce833cca1b5929f"
$.ajax({
url: queryURL,
method: "GET"
})
.done(function(response) {
// loop through the response trails and add info to the site
for (i = 0; i < response.trails.length; i++) {
var contentDivTitle = $("<div> class='newTrailTitle'");
var contentDivMain = $("<div> class='newTrailDescription'");
contentDivTitle.text("Name: " + response.trails[i].name + " Location: " + response.trails[i].location);
contentDivMain.text("Summary: " + response.trails[i].summary);
$("#search-results").append(contentDivTitle);
$("#search-results").append(contentDivMain);
}
});
});
});
html,
body {
background-color: black;
margin: 10px;
}
h1,
h3 {
color: white;
text-align: center;
padding: 5px;
line-height: 1px;
}
h1 {
/* automatically changes lowercase to uppercase text; */
text-transform: uppercase;
}
sub {
color: white;
text-align: center;
line-height: 1px;
font-size: 15px;
font-weight: lighter;
}
.container {
display: grid;
grid-template-columns: auto;
grid-template-rows: 800px 500px 200px 50px 100px;
grid-gap: 3px;
}
.container>div {
display: flex;
justify-content: center;
align-items: center;
font-size: 1em;
}
.container>div:nth-child(1n) {
background-color: black;
}
.container>div:nth-child(2n) {
background-color: blue;
}
.container>div:nth-child(3n) {
background-color: red;
}
.container>div:nth-child(4n) {
background-color: yellow;
}
.container>div:nth-child(5n) {
background-color: green;
}
label {
color: white;
}
#main {
background-image: url("assets/images/etienne-bosiger-367964.jpg");
background-size: cover;
background-repeat: no-repeat;
}
#au,
#cr {
display: block;
margin: auto;
}
#groupPic {
padding: 10px;
}
<html>
<head>
<link rel="stylesheet" href="test.css">
</head>
<body>
<div class="container">
<div id="main">
<div id="title">
<h1>kairns<sub>®</sub></h1>
<h3>"find your trail"</h3>
<div class="search-div">
<label for="txtAddress">Enter Address: </label>
<input type="text" name="txtAddress" id="txtAddress">
<button type="button" id="submit">Search</button>
</div>
</div>
</div>
<div class="search-results" id="search-results">2</div>
<div>
<p id="au">About Us</p>
<img id="groupPic" src="http://via.placeholder.com/150x150" alt="placeholder image">
<p id="cr">Copyright 2018.</p>
</div>
<div>4</div>
<div>
<p>Powered by
Google Maps,
Open Weather Map, and Hiking Project
</p>
</div>
</div>
<!-- JAVASCRIPT -->
<!-- jQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- custom javaScript -->
<script type='text/javascript' src='assets/javascript/logic.js'></script>
</body>
</html>
All in-flow children of the #search-results element will align vertically if you apply:
#search-results {
display: flex;
flex-direction: column;
}

Center bootstrap button in xs

I have spent literally hours on this, I cannot get this button centered when the screen width entered xs mode, it started to position itself based off of the left side. I've tried looking in the bootstrap and cant find any clear indication as to why this happens.
Here is my code, mainly the third main div block with btn-posit class inside and the media queries 461-767px. Thanks
https://codepen.io/fullmetal7777/pen/RgKagp
<div class="container">
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-8 col-xs-10 text-center btn-posit">
<button class="btn btn-primary twit-btn"><i class="fa fa-twitter-square fa-2x" aria-hidden="true"><span id="twit-Text">Tweet it</span></i></button>
<button class="btn btn-default quote-btn"><div id="whole-text">Get Quote</div></button>
</div>
</div>
This will get you close to what you want.
The issues:
The column with the buttons in had a class of col-xs-10 which should be col-xs-12 if you want the buttons to be centered.
The twitter button still had margin right on it for the xs size, which was pushing it to the left, preventing it from centering.
https://codepen.io/anon/pen/xrdPVb
If you just want the menus centered, you don't need to use the col-* classes to wrap them. Remove those and apply .text-center (which you already have), then remove all of the media queries you were using to offset the margin and try to center that column. But then I think you have some display issues from using transform: translateX(-1); so I just reversed the image and removed that transform line. The less work the browser has to do, the better, so if you can change the image, I'd just do that.
$(document).ready(function(){
var quotes = {
Mario: ["So long-a-Bowser!", "Nighty nighty. Ah spaghetti. Ah, ravioli. Ahh, mama mia.", "You know what they say: all toasters toast toast."],
Luigi: ["Let's-a go...", "Oh yeah! Who's number one now?! Luigi!", "Now, THIS is where the real action is"],
Bowser: ["Im HUUUUGE! Even scarier up close, huh?", "GAH HA HA HA! There's no WAY you're ready for a round against ME. Keep practicing, pip-squeak!"],
Peach: ['Oh, did I win?', "Go Peachy, Go Peachy, Go Peachy! Yay! Woohoo!"],
Yoshi: ['Yoshi!'],
Fox: ["This is Fox, returning to base!", "Better luck next time, Falco!"],
Falcon: ["Falcon Kick!", 'Blue Falcon!', 'Show me your moves!'],
Marth: ["Konkaiwa bokuno kachidane! (It's my victory this time!)", "Kyoumo ikinobiru kotoga dekita. (Even today I was able to survive.)",
"Bokuwa makeru wake niwa ikenainda! (There's no way I can lose!)"],
Pit: ["Three Sacred Treasures!", "It's game over for you!", "That all you got?"],
Link: ["....."],
Ike: ["Great... AETHER!", "I fight for my friends.", "You'll get no sympathy from me."],
Lucario: ["Behold, the power of Aura!", "The Aura is with me!", "Max Aura!"],
'Wii Fit Trainer': ["High energy, move that body!", "Salute the sun!", "Work hard to tone that tummy."],
Sheik: ['I\'ve been waiting for you, Hero of Time...', 'The flow of time is always cruel.'],
Ganandorf: ['Hero? ...I\'ve outlived more "heroes" than you can possibly imagine.', 'Behold! The power of the Demon King!',
'I am Ganondorf, the Demon King. Don\'t take that title lightly.'],
Mac: ["Let 'em have it, Mac!", "Way to go, Mac! You're the champ, baby!", "Nice moves, Mac. I can barely keep my eyes on you, son."],
Palutena: ["You shall be purified.", "No one can hide from the light.", "Celestial Fireworks!"],
Robin: ["The key to victory lies within.", "I'm always three steps ahead.", "It seems our fates are joined."],
Shulk: ["Now it's Shulk time!", "I can change the future!", "The future is ours to decide!"],
Sonic: ["That was almost too easy!", "Let's do that again some time!"],
Falco: ["Personally, I prefer the air!", "You aren't worth the trouble."],
Wario: ["Wa-Wa-Wa!", "Time for victory parade."],
'Toon Link': ["....."],
Lucina: ["The future is not written!", "Time to change fate!"]
}
var nameArr = ['Mario', 'Luigi', 'Bowser', 'Peach', 'Yoshi', 'Lucina', 'bowser jr', 'Wario', 'game and watch', 'donkeyk', 'diddyk', 'Link', 'Zelda',
'Sheik', 'Ganandorf', 'Toon Link', 'samus', 'zero suite samus', 'Pit', 'Palutena', 'Marth', 'Ike', 'Robin', 'kirby', 'king deedeedee', 'meta knight',
'Mac', 'placeholder', 'Fox', 'Falco', 'pikachu', 'charizard', 'Lucario', 'jigglypuff', 'Greninja', 'duck hunt', 'Rob', 'ness', 'Falcon', 'villager',
'olimar', 'Wii Fit Trainer', 'dr mario', 'dark pit', 'Lucina', 'Shulk', 'pacman', 'Megaman', 'Sonic'];
var imgurID = '0RQtP';
var key = "cfb3f86a62ab07c";
function randomFxn(){
$.ajax({
type: 'GET',
url: 'https://api.imgur.com/3/album/' + imgurID + '/images',
headers: {'Authorization': 'Client-ID '+ key},
}).done(function(data) {
showZones(data)
});
}
var lastNum = '70';
function showZones(jsonData){
var name = '';
do{
var nameNum = Math.floor(Math.random()*(Object.keys(quotes).length));
// var nameNum = 70;
console.log(nameNum);
} while (nameNum == lastNum)
console.log(lastNum);
lastNum = nameNum;
console.log(lastNum);
name = Object.keys(quotes)[nameNum];
var quoteArrLength = quotes[name].length;
var randQuoteNum = Math.floor(Math.random()*quoteArrLength)
var randQuote = '\"' + quotes[name][randQuoteNum] + '\"';
var indexMult = (nameArr.indexOf(name)*8);
var addToIndex = Math.floor(Math.random()*8);
var url = jsonData.data[(indexMult)+addToIndex].link;
var imgCss = 'url(' + url + ')';
var isReverse = Math.floor(Math.random()*2);
$('h3').text('-' + name);
$('h2').text('Hero? ...I\'ve outlived more "heroes" than you can possibly imagine.');
$('.bg').fadeOut(500, function() {
if(isReverse==1){
$(this).css({'background-image': imgCss, 'transform': 'scaleX(1)'}).fadeIn(700);
}
else{
$(this).css({'background-image': imgCss, 'transform': 'scaleX(-1)'}).fadeIn(700);
}
});
}
var num = 0;
$('.quote-btn').click(function(){
if (num == 0){
num++;
randomFxn();
setTimeout(function(){
num = 0;
}, 1200);
}
});
});
body, html{
height: 100%;
}
.bg,
.quote-btn {
background-repeat: no-repeat;
background-size: cover;
}
.bg{
background-image: url("http://i.imgur.com/sxwO4y3.jpg");
height: 100%;
background-size: 70% 100%;
}
.jumbotron{
margin-left: 16.66666667%;
margin-top: -78vh;
background-color: rgba(100, 100, 100, 0.4);
border-style: solid;
border-color: rgba(0, 0, 0, 0);
}
h2, h3{
color: white;
opacity: 1;
font-weight: 900;
}
h2{
margin-top: -3vh;
margin-left: -1.7vw;
}
h3{
float: right;
}
.quote-btn {
border-color: #5e1111 #5e1111 hsl(0, 69%, 17%);
background-image: url("http://www.wtfgamersonly.com/wp-content/uploads/2015/06/Super-Smash-Bros.-img.2.jpg");
background-position: 50% 60%;
height: 45px;
width: 140px;
}
.twit-btn{
height: 45px;
width: 140px;
margin-right: 35px;
}
#whole-text{
font-weight: 800;
color: #BC1818;
font-size: 22px;
}
.btn.quote-btn:focus,
.btn.quote-btn:active:focus,
.btn.quote-btn.active:focus,
.btn.quote-btn.focus,
.btn.quote-btn:active.focus,
.btn.quote-btn.active.focus,
.btn.twit-btn:focus,
.btn.twit-btn:active:focus,
.btn.twit-btn.active:focus,
.btn.twit-btn.focus,
.btn.twit-btn:active.focus,
.btn.twit-btn.active.focus{
outline-color: none;
outline-style: none;
border-color: #5e1111 #5e1111 hsl(0, 69%, 17%);
}
.btn.quote-btn:hover{
border-style: none;
}
.btn.quote-btn:active{
background-image: url("http://www.wtfgamersonly.com/wp-content/uploads/2015/06/Super-Smash-Bros.-img.2.jpg");
opacity: .8;
}
#media only screen and (max-height: 568px){
.jumbotron{
margin-top:-89vh;
}
}
#media only screen and (min-height: 569px){
.jumbotron{
margin-top:-80vh;
}
.btn-posit {
margin-top: -42vh;
}
}
#media only screen and (min-width: 0px) and (max-width: 1199px){
.bg{
background-size: cover;
background-position: center;
}
}
/*medium*/
#media only screen and (min-width: 992px) and (max-width: 1199px) {
.jumbotron{
margin-left: 8.33333333%;
}
}
/*small*/
#media only screen and (min-width: 768px) and (max-width: 991px){
.jumbotron{
margin-left: 4.15%;
}
}
/*xs*/
#media only screen and (min-width: 461px) and (max-width: 767px){
.jumbotron{
margin-left: 8.33333333%;
}
.btn-posit{
width: auto;
}
}
#media only screen and (min-width: 0px) and (max-width: 460px) {
h2{
font-size: 22px;
}
h3{
font-size: 18px;
}
.btn-posit{
/*padding-left: 78px; */
margin-left: 1%;
}
.jumbotron{
margin-left: 8%;
}
.twit-btn{
margin-right: 55px;
width: auto;
}
#twit-text{
display: none;
}
}
/*#media only screen and (min-width: 0px) and (max-width: 422px) {
h2{
font-size: 22px;
}
h3{
font-size: 18px;
}
.twit-btn{
width: auto;
margin-right: 10px;
}
.btn-posit{
padding-left: 15%;
}
#twit-text{
display: none;
}
}*/
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://use.fontawesome.com/5ad62430a6.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<html>
<head>
<title>AwesomeDesigns Random Quote Generator</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="bg"></div>
<div class="container">
<div class="row">
<div class="col-lg-8 col-md-10 col-sm-11 col-xs-10 jumbotron">
<h2>"Andrews Random Quote Generator. "</h2>
<h3>-Andrew Hickman</h3>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="text-center btn-posit">
<button class="btn btn-primary twit-btn"><i class="fa fa-twitter-square fa-2x" aria-hidden="true"><span id="twit-Text">Tweet it</span></i></button>
<button class="btn btn-default quote-btn"><div id="whole-text">Get Quote</div></button>
</div>
</div>
</div>
</html>
adding text-center class seemed to be the fix!

How to display custom video controls even in fullscreen

Update: Can't see to get things working in Firefox : (
How can I display custom video controls when the in fullscreen mode in modern browsers?
They disappear as soon as I go fullscreen. I'd like them to be available, and then I'll write some JavaScript to hide them on inactivity and show them once someone wiggles their mouse around.
HTML:
<video#video src="vid.mp4" preload poster="/images/poster.jpg">
<iframe src="https://youtube.com/embed/id" frameborder="0" allowfullscreen>
</video>
JS:
var bigPlayButton = document.getElementById('big-play-button')
var video = document.getElementById('video')
var playPauseButton = document.getElementById('play-pause')
var fullscreen = document.getElementById('fullscreen')
function toggleFullScreen() {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen()
} else {
if (document.exitFullscreen) {
document.exitFullscreen()
}
}
}
fullscreen.addEventListener('click', function (event) {
if (!video.classList.contains('fullscreen')) {
video.requestFullscreen()
} else {
document.exitFullscreen()
}
}, false)
// Detect FullScreen changes and adjust button
document.addEventListener('fullscreenchange', function (event) {
if (document.fullscreenElement) {
fullscreen.children[0].src = '/images/nofullscreen.svg'
video.classList.add('fullscreen')
} else {
fullscreen.children[0].src = '/images/fullscreen.svg'
video.classList.remove('fullscreen')
}
}, false)
CSS
video::-webkit-media-controls {
display: none !important;
}
#custom-video-controls {
z-index: 2147483648;
}
I'm using this polyfill: https://github.com/neovov/Fullscreen-API-Polyfill
Edit
The significant change was targeting the parent tag: .vidFrame for fullscreen instead of the <video> tag as per Kaido's comment.
HTML5 video's controls need special handling if you want to override them. I'm assuming you want to do that since the controls already have the full screen feature built in the controls. This demo implements:
classList for toggling the button#fullScreen states of .on and .off and button#playPause states of .play and .pause.
:fullscreen pseudo-class to insure .vidBar is on the bottom when in full screen mode.
Shadow DOM CSS Styles that are needed to override the native player's controls.
Fullscreen API vendor specific methods to enter and exit full screen mode of course.
There's no volume slider, mute button, or scrubber, just the full screen button (button#fullScreen) and play button (button#playPause). If you want them, ask another question.
Details are commented in source.
It looks as if the Snippet isn't fully functional, so here's a functional Plunker. If that version cannot be reached, then review the embedded Plunker and click the full view button:
Demo
Note: SO sandbox has changed so this demo is not fully functional go to the links mentioned previously or copy and paste the demo on a text editor.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Full Screen Video Toggle</title>
<style>
.vidFrame { position: relative; top: 10%; width: 320px; height: auto; min-height: 180px; outline: 1px dashed red; }
.vidBar { position: absolute; bottom: 0; right: 0; left: 0; height: 40px; width: 99%; }
#fullScreen { position: absolute; bottom: 0; right: 0; width: 36px; height: 36px; outline: none; border: 1px solid transparent; border-radius: 6px; display: block; cursor: pointer; }
#fullScreen:hover { border: 1px groove #0ef; }
.on, .off { background: url('https://i.imgur.com/0FTwh6M.png') no-repeat; width: 36px; height: 36px; }
.off { background-position: 0 0 }
.on { background-position: -1px -50px }
#playPause { position: absolute; bottom: 0; left: 0; width: 36px; height: 36px; background: none; font-size: 36px; color: #0ff; line-height: 1; border: 1px solid transparent; display: block; cursor: pointer; outline: none; }
#playPause.play:before { content: '\25b6'; }
#playPause.pause:before { content: '\275a\275a'; }
.vid { position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: auto; display: block; z-index: 1; outline: 1px dotted blue; }
/*
Fullscreen Pseudo-class:
https://developer.mozilla.org/en-US/docs/Web/CSS/:fullscreen
*/
.vidBar:-moz-full-screen { position: fixed; }
.vidBar:-webkit-full-screen { position: fixed; }
.vidBar:-ms-fullscreen { position: fixed; }
.vidBar:fullscreen { position: fixed; }
/*
Special Shadow DOM Settings to Override Default Controls:
https://css-tricks.com/custom-controls-in-html5-video-full-screen/
*/
video::-webkit-media-controls-enclosure { display:none !important; }
.vidBar { z-index: 2147483648; }
</style>
</head>
<body>
<figure class="vidFrame">
<video id="vid1" class="vid" src="http://techslides.com/demos/sample-videos/small.mp4"></video>
<figcaption class="vidBar">
<button id='playPause' class="play" title="Play/Pause Video"></button>
<button id='fullScreen' class="on" title="Enter/Exit Full Screen"></button>
</figcaption>
</figure>
<script>
/*
Toggle Button with classList:
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
*/
var fullBtn = document.getElementById('fullScreen');
var playBtn = document.getElementById('playPause');
playBtn.addEventListener('click', function(event) {
var player = document.getElementById('vid1');
if(player.paused) {
playBtn.classList.remove('play');
playBtn.classList.add('pause');
player.play();
} else {
playBtn.classList.add('play');
playBtn.classList.remove('pause');
player.pause();
}
}, false);
fullBtn.addEventListener('click', function(event) {
var tgtEle = document.querySelector('.vidFrame');
var onOrOff = fullBtn.classList.contains('on');
if (onOrOff) {
enterFS(tgtEle);
fullBtn.classList.remove('on');
fullBtn.classList.add('off');
} else {
exitFS();
fullBtn.classList.add('on');
fullBtn.classList.remove('off');
}
}, false);
/*
Fullscreen API:
https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API
*/
function enterFS(element) {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
}
}
function exitFS() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
}
</script>
</body>
</html>
Use the Fullscreen API on the container element, not on the video
As #Kaiido says in the comments:
You have to call the enterFS method on the container element, not on
the video one.
So the answer is to use the Fullscreen API on the container element rather than the <video> element. This enables providing custom controls in that container which is now all in fullscreen.
For reference, that is the existing enterFS() function from the question:
function enterFS(element) {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
}
}
I posted this answer because I had to read the page three times to figure out what was going on here.
There is great information in #zer00ne's answer that is relevant to others with similar issues, but it doesn't directly answer #Costa's original problem, which was previously only answered in a comment.