CSS Image Clipping as Full Screen - html

I am by no means a CSS expert (as you can see from my code) but I almost got this working the way I want but I was having some slight formatting problems. Basically I am trying to make a page that will go through a ppt deck (exported as .jpgs). It is extremely straight forward with only 2 buttons that go to the next or previous slide and displays the image full screen.
The issue I am seeing is the image keeps getting cropped, specifically the top. It will often display fine but when I switch images the top 5ish% of the screen is getting clipped no matter how much I play with the padding. Hopefully this is an easy fix... any help would be greatly appreciated...
<html>
<head>
<style>
body, html {
height: 100%;
}
.bg {
/* The image used */
background-image: url("Slide1.JPG");
/* Full height */
height: 90%;
/* Center and scale the image nicely */
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.center {
position: relative;
vertical-align: middle;
top: 100%;
}
.button {
background-color: #0033ff; /* Blue */
border: solid;
border-width: medium;
border-color: black;
color: white;
padding: 2px 2px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
vertical-align: text-top;
height: 5%;
width: 40%;
font-size: 100%;
}
</style>
<script src="jquery-3.2.1.min.js"></script>
<script type="text/javascript">
var refreshIntervalId = setInterval(autoNextSlide, 8000);
var clicks = 1;
var isPaused = false;
var time = 0;
function pictureBack() {
clicks -= 1;
checkImage("Slide" + clicks + ".JPG", function () { }, function () { clicks = 1; });
// alert("slides/Slide" + clicks + ".JPG");
var str_image = 'background-image: url("Slide' + clicks + '.JPG");';
document.getElementById('bkground').style.cssText = str_image
isPaused = true;
time = 0;
}
function pictureNext() {
clicks += 1;
checkImage("Slide" + clicks + ".JPG", function () { }, function () { clicks = 1; });
//alert("slides/Slide" + clicks + ".JPG");
var str_image = 'background-image: url("Slide' + clicks + '.JPG");';
document.getElementById('bkground').style.cssText = str_image
isPaused = true;
time = 0;
}
function checkImage(imageSrc, good, bad) {
var img = new Image();
img.onload = good;
img.onerror = bad;
img.src = imageSrc;
}
function autoNextSlide() {
if (isPaused) {
time++;
if (time > 4) {
isPaused = false
};
//isPaused = true
//alert("is paused")
} else {
pictureNext();
time = 0;
isPaused = false;
};
}
</script>
</head>
<body>
<div class="bg" id="bkground">
<div class="center">
<p><input type="button" class="button" id="theButton" value="Previous" onclick="pictureBack()" style='float:left;' padding="10%"></p>
<p><input type="button" class="button" id="theButton2" value="Next" onclick="pictureNext()" style='float:right;'></p>
</div>
</div>
</body>
</html>

Use:
.bg {
/* The image used */
background-image: url("Slide1.JPG");
/* Full height */
height: 90%;
/* Center and scale the image nicely */
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
}
Instead of:
.bg {
/* The image used */
background-image: url("Slide1.JPG");
/* Full height */
height: 90%;
/* Center and scale the image nicely */
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
Cover makes the image cover the element in it's entirity but cuts off the image.
With 100% 100% it's makes it fit fully no matter what. It may skew the image a tad on some devices but it you aren't worried about mobile use, you should be fine.

Related

Reverse HTML font colour from background

I'm building a website for my friend, and i've hit a snag.
The background is a moving image, and i would like the font colour of the main title to be a reverse of it on every frame. I'm sure this would be impossible to do without CSS, but i don't know how to make it work. I also was wondering if there was a way to make it affect not just the whole thing, but like each letter or pixel? I'm not sure.
Here's my code:
var isIncrementing = false;
var intervalId;
var numberElement = document.getElementById("number");
var toggleButton = document.getElementById("toggleButton");
function toggleIncrement() {
if (!isIncrementing) {
isIncrementing = true;
intervalId = setInterval(incrementNumber, 0); // Increment every second
toggleButton.innerHTML = "Click to deactivate Duckie-fier";
} else {
isIncrementing = false;
clearInterval(intervalId);
toggleButton.innerHTML = "Click to activate Duckie-fier";
}
}
function incrementNumber() {
var number = parseInt(numberElement.innerHTML);
numberElement.innerHTML = number + 1;
}
img {
width: 30%;
height: 70%;
}
body {
background-image: url('https://media3.giphy.com/media/pR1ztNFfPS7wa2eYfY/200w.gif?cid=6c09b9523w4yesgqef8dno4mrrz98shnzgkv7dhgl4dqd9qp&rid=200w.gif&ct=g');
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
font-family:courier;
}
<h1>Number of Duckies: <span id="number">0</span></h1>
<button style="font-family: Courier;" id="toggleButton" onclick="toggleIncrement()">Click to activate Duckie-fier</button>
<br>
</br>
<img src="https://i.kym-cdn.com/photos/images/original/002/429/796/96c.gif">
I want it to be updated every frame of the background, if possible.
The answer could be using the mix-blend-mode: difference; property, however it appears to not have universal browser support so it might not be the best solution.
var isIncrementing = false;
var intervalId;
var numberElement = document.getElementById("number");
var toggleButton = document.getElementById("toggleButton");
function toggleIncrement() {
if (!isIncrementing) {
isIncrementing = true;
intervalId = setInterval(incrementNumber, 0); // Increment every second
toggleButton.innerHTML = "Click to deactivate Duckie-fier";
} else {
isIncrementing = false;
clearInterval(intervalId);
toggleButton.innerHTML = "Click to activate Duckie-fier";
}
}
function incrementNumber() {
var number = parseInt(numberElement.innerHTML);
numberElement.innerHTML = number + 1;
}
img {
width: 30%;
height: 70%;
}
body {
background-image: url('https://media3.giphy.com/media/pR1ztNFfPS7wa2eYfY/200w.gif?cid=6c09b9523w4yesgqef8dno4mrrz98shnzgkv7dhgl4dqd9qp&rid=200w.gif&ct=g');
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
font-family: courier;
}
h1 {
color: white;
mix-blend-mode: difference;
}
<h1>Number of Duckies: <span id="number">0</span></h1>
<button style="font-family: Courier;" id="toggleButton" onclick="toggleIncrement()">Click to activate Duckie-fier</button>
<br>
</br>
<img src="https://i.kym-cdn.com/photos/images/original/002/429/796/96c.gif">

Remove class at top of page isn't always working

I've got a header that I want to disappear (move above the top of the browser screen) when the user scrolls down, then when the user scrolls back up I want the header to reappear (move back down) and also to gain a solid white background behind it.
All of this is working fine, but then I want the white background to be removed if the user scrolls back up to the very top of the page again (so it's just the header visible but with no white background).
I've cobbled together the code for this, and it's pretty much working - but, for some reason, in certain circumstances, the white background isn't being removed?!
It seems to be if you've scrolled back up enough to make the header reappear with the white background, but not all the way top the top, and then scroll the rest of the way then the white background doesn't disappear for some reason.
Sorry, I've probably not explained that very well, but here's my code. If someone is able to replicate the bug I'm getting and offer an explanation I'd be very grateful!
Thanks
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 30;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 30);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('header-down').addClass('header-up').removeClass('header-solid');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('header-up').addClass('header-down').addClass('header-solid');
}
}
lastScrollTop = st;
};
$(function () {
$(window).scroll(function () {
var top_offset = $(window).scrollTop();
if (top_offset == 0) {
$('header').removeClass('header-solid');
}
})
});
body {
margin: 0;
background: url('https://images.unsplash.com/3/doctype-hi-res.jpg?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=2246&q=80');
background-size: cover;
}
.wrapper {
width: 100%;
height: 3000px;
}
header {
display: flex;
width: 100%;
padding: 20px 50px;
position: fixed;
box-sizing: border-box;
transition: 300ms all ease-in-out;
margin-top: 0px;
}
.header-logo {
width: 200px;
}
.header-nav {
flex-grow: 1;
text-align: center;
}
.header-socials {
width: 200px;
text-align: right;
}
.header-up {
margin-top: -60px;
}
.header-down {
margin-top: 0px;
}
.header-solid {
background-color: #FFFFFF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<header class="header-down">
<div class="header-logo">
<img src="#" class="img-header-logo"/>
</div>
<div class="header-nav">
One Two Three Four Five
</div>
<div class="header-socials">
Social Links
</div>
</header>
</div>

switching .carousel height and width depening on landscape or portrait photo

I use the code below to fit my landscape(4:3) photo's in a carousel. But I would like to change the width and height of the .carousel depending on the photo(landscape or portrait). How can I do that?
html {
height: 100%;
width: 100%;
}
body {
height: 100%;
width: 100%;
display: block;
}
.carousel {
/* the percentages below are for a 4:3 landscape photo(1600x1200) */
height: 60%;
width: 70%;
}
/* I need to set height : 70%; and width: 60% for portrait */
Should I add an class to the carousel-item to indicate that it's a landscape or portrait photo?
Create one class for portrait and one for landscape. When the image loads or when you get the image size then determine if it is portrait or landscape and then add the appropriate class to the image or carousel container.
// list of images - as requested you can put this list in a separate js file
// make sure it is before the other code below
var imagesArray = ["https://lorempixel.com/300/500/animals/1", "https://lorempixel.com/300/500/animals/2", "https://lorempixel.com/500/300/animals/1","https://lorempixel.com/500/300/animals/2","https://lorempixel.com/500/300/city/1","https://lorempixel.com/300/500/city/2"];
// when the user clicks the random button
// we get a random image from our list of URLS
// and then set that as the source of the image
function displayImage(direction, isURL) {
var image = document.getElementById("myImage");
var label = document.getElementById("loadingLabel");
var list = imagesArray.slice(); //make a copy
var currentURL = image.src;
var currentIndex;
var index = 0;
var numberOfImages = list.length;
if (isURL==true) {
currentURL = direction;
}
currentIndex = list.indexOf(currentURL);
if (direction=="next") {
index = currentIndex>=list.length-1 ? 0 : currentIndex+1;
}
else if (direction=="previous") {
index = currentIndex<=0 ? list.length-1 : currentIndex-1;
}
else if (direction=="random") {
list.splice(currentIndex,1);
index = Math.floor(Math.random()*list.length);
}
else if (direction=="start") {
index = 0;
}
else if (direction=="end") {
index = list.length-1;
}
else if (isURL) {
if (currentIndex==-1) {
console.log("Image not found in images array. Check the URL");
return;
}
index = currentIndex;
}
else {
console.log("Direction not specified");
}
image.src = list[index];
label.innerHTML = "Loading " + list[index] + "...";
label.title = list[index];
updateNavigationLabel();
}
// this handles when the image has finished loading
// we check if the image is portrait or landscape
// if it is landscape we set the landscape class
// if it is portrait we set the portrait class
function imageLoadHandler(event) {
var image = document.getElementById("myImage");
var carousel = document.getElementById("myCarousel");
var label = document.getElementById("loadingLabel");
var width = image.naturalWidth;
var height = image.naturalHeight;
var isPortrait = width<height;
var isSquare = width==height;
carousel.classList.remove("portrait");
carousel.classList.remove("landscape");
var caption = width + "x" + height;
if (isPortrait) {
caption = "Portrait (" + caption + ")";
carousel.classList.add("portrait");
}
else if (isPortrait==false) {
caption = "Landscape (" + caption + ")";
carousel.classList.add("landscape");
}
image.caption = caption;
label.innerHTML = caption;
updateNavigationLabel();
}
function updateNavigationLabel() {
var image = document.getElementById("myImage");
var label = document.getElementById("navigationLabel");
var list = imagesArray.slice(); //make a copy
var numberOfImages = list.length;
var currentURL = image.src;
currentIndex = list.indexOf(currentURL);
label.innerHTML = currentIndex+1 +" of " + numberOfImages;
}
window.addEventListener("DOMContentLoaded", function() {
var element = document.getElementById("myImage");
var button = document.getElementById("button");
var carousel = document.getElementById("myCarousel");
// listen for when an image loads
element.addEventListener("load", imageLoadHandler);
// listen for when the user clicks on the random button
button.addEventListener("click", function() {
displayImage('random')
});
// Options - load an image when the page loads
// displayImage("start"); // use to load the first image
// displayImage("end"); // use to load the last image
// displayImage("random"); // use to load a random image
// displayImage("specified", "https://lorempixel.com/300/500/animals/2"); // use to load an image in the images array
displayImage("https://lorempixel.com/300/500/animals/2", true);
});
.landscape {
height: 60%;
width: 70%;
outline:2px solid blue;
}
.portrait {
height: 70%;
width: 60%;
outline:2px solid purple;
}
#myCarousel {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
#myImage {
position: absolute;
left: 50%;
transform: translateX(-50%);
outline: 1px dashed red;
height: 100%;
width: 100%;
object-fit: contain;
}
#button {
position: fixed;
right: 10px;
top: 50px;
}
#loadingLabel {
position: absolute;
bottom: -20px;
left: 50%;
transform: translateX(-50%);
font: 10px sans-serif;
white-space: nowrap;
}
#navigationLabel {
font: 10px sans-serif;
}
#navigation {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
font: 10px sans-serif;
}
<!-- optionally set images in separate file. order before the main javascript -->
<script src="myimages.js"></script>
<div id="myCarousel" class="landscape">
<img id="myImage">
<label id="loadingLabel"></label>
</div>
<button id="button">random</button>
<div id="navigation">
<button id="prev" onclick="displayImage('previous')">prev</button>
<label id="navigationLabel"></label>
<button id="next" onclick="displayImage('next')">next</button>
</div>

How to change data visible range to % percent

I am using this for my header that changes in a one page scroll up and down page. I noticed that it's not responsive so i am asking you if you maybe know a way to make that responsive. Like changing the 0-690 into a percentage so that it will work on mobile and also on a tv screen.
HTML
<div class="header header-1" data-visible-range="0-690">Portfolio</div>
<div class="header header-2" data-visible-range="691-2100">Services</div>
<div class="header header-3" data-visible-range="2101-">Contact</div>
CSS
.header-1 {
background-color:dimgray;
display: block;
}
.header-2 {
background-color:dimgray;
}
.header-3 {
background-color:dimgray;
}
.header {
position: fixed;
top: 0;
left: 0;
height:8vmax;
width: 100%;
display: none;
visibility:hidden;
transition: visibility .4s, opacity .4s ease-in-out;opacity:0;
font-size:4vmax;padding:1.58vmax;color:white;
}
What if, instead of basing it off pixels, you just checked to see if an element hit the top of the page, and then changed the header?
We'll call these elements "triggers." See my code below for an example of how they work.
let updateHeader = () => {
let scrollTop = $(window).scrollTop(),
triggerTitle = "Hi";
$('.trigger').each((i, el) => {
let topPos = $(el).offset().top,
distance = topPos - scrollTop;
if (distance < 0)
triggerTitle = $(el).data('title');
});
$('header h2').text(triggerTitle);
}
$(window).scroll(updateHeader);
$(window).on('touchmove', updateHeader);
body {
margin: 0;
}
#container {
height: 1000px;
}
header {
width: 100%;
position: fixed;
top: 0;
background-color: red;
}
p {
margin: 200px 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<header><h2>Hi</h2></header>
<p class="trigger" data-title="section1">
trigger1
</p>
<p class="trigger" data-title="section2">
trigger2
</p>
<p class="trigger" data-title="section3">
trigger3
</p>
</div>
As you scroll down the page, each trigger hits the top of the page, and the text in the header will change to the the value of the latest trigger's data-title. You could position these triggers appropriately above each of your website's sections, so that, no matter what size the screen, the header should update at the right time. Here's a codepen.
EDIT
Try this JS instead for maximum compatibility (no es6 involved).
function updateHeader() {
var scrollTop = $(window).scrollTop(),
triggerTitle = "Hi";
$('.trigger').each(function(i, el) {
var topPos = $(el).offset().top,
distance = topPos - scrollTop;
if (distance < 0)
triggerTitle = $(el).data('title');
});
$('header h2').text(triggerTitle);
}
$(window).scroll(updateHeader);
$(window).on('touchmove', updateHeader);

How can I make an Upvote/Downvote button?

I'm trying to make an upvote/downvote the same way that it's done on SO and Reddit, from what I can see they use arrow images as backgrounds and then position it, but I'm a CSS newbie and I need someone to walk me through it.
You could do it by adding a different picture to the background, one for every state of the button. There is however a cleaner, easier, more modern way of achieving this result: Sprites.
A sprite is an image that is saved as a part of a larger image. One of the biggest advantages of using sprites is the reduction of round-trips to the server for all the images to just one request for the Sprites. The element to display a picture has the image as background. The background is moved relative to the element so the element displays only part of the image. Like when you move a photo-frame over a poster (or in this case: moving the poster under the frame)
At SO they make an image that contains all the states for the button. They give the element for the button (a span in this case) a fixed width and height and add the background to it with CSS. Then toggle a class for the state (on or off) with javascript on the click event. Now the only thing you have to do in CSS is change the position of the background with CSS classes:
for (const btn of document.querySelectorAll('.vote')) {
btn.addEventListener('click', event => {
event.currentTarget.classList.toggle('on');
});
}
.vote {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('http://i.stack.imgur.com/iqN2k.png');
background-position: 0 -25px;
}
.vote.on {
background-position: 0 2px;
}
Click to vote (using sprites): <span class="sprite vote"> </span>
You can easily add more states to the sprites like 'hover' and 'active' just the same way. SO even puts all the images for the whole page in a single image. You can verify this with firebug or the Chrome developer tools. Look for 'sprites.png'.
Update (2020)
It's been 10 years since I answered this question and in this time,
the landscape has changed. Now you can use inline svg as well to achieve this effect. I've updated the code snippet to use svg. This is how stackoverflow currently does this.
It works by toggling the color property of a surrounding span element on button click. The span element contains an inline svg image of an arrow. The fill property of the path that makes up the arrow is initialized with currentColor, which instructs it to take whatever is the current text color.
for (const btn of document.querySelectorAll('.vote')) {
btn.addEventListener('click', event => {
event.currentTarget.classList.toggle('on');
});
}
.vote {
display: inline-block;
cursor: pointer;
color: #687074
}
.vote.on {
color: #f48024
}
Click to vote (using svg):
<span class="vote">
<svg width="36" height="36">
<path d="M2 10h32L18 26 2 10z" fill="currentColor"></path>
</svg>
</span>
You can do it by using two simple images ... design two images in some image editors like Photoshop, if u don't have MSPaint...
CSS code is
#voting{
width:30px;
height:40px;
}
.upvote{
width:30px;
height: 20px;
cursor: pointer;
}
.downvote{
width:30px;
height: 20px;
background: url('downvote.jpg') 0 0 no-repeat;
cursor: pointer;
}
HTML code :
<div id="voting">
<div class="upvote"></div>
<div class="downvote"></div>
</div>
I'm doing project on django, and I'm trying to implement up-vote and down-vote on many posts, I've taken #Jan's code partly and finished it.
vote.html
<span onclick="like_function({{user_answer.pk}})" id="like-{{user_answer.pk}}" class="vote_up_off"></span>
<div id="counter-{{user_answer.pk}}">0</div>
<span onclick="dislike_function({{user_answer.pk}})" id="dislike-{{user_answer.pk}}" class="vote_down_off"></span>
vote.css
/* like dislike button */
.vote_up_off {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url(' https://i.stack.imgur.com/nxBdX.png');
background-position: 0 -25px;
margin-left: 5px;
}
.vote_up_on {
background-position: 0 2px;
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('https://i.stack.imgur.com/nxBdX.png');
margin-left: 5px;
}
.vote_down_off {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('https://i.stack.imgur.com/vWw7n.png');
background-position: 0 -1px;
margin-top: 3px;
}
.vote_down_on {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('https://i.stack.imgur.com/vWw7n.png');
background-position: 0 -28px;
margin-top: 3px;
}
vote.js
function like_function(answer_id) {
var like_button = document.getElementById('like-'+answer_id);
var dislike_button = document.getElementById('dislike-'+answer_id);
var counter_element = document.getElementById('counter-'+answer_id);
let current_counter = parseInt(counter_element.innerText);
//check if dislike is on(true) or off(false)
let dislike_state = false
if (dislike_button.className == "vote_down_on") {
dislike_state = true
}
else {
dislike_state = false
}
//if dislike is checked
if (dislike_state) {
current_counter += 2;
dislike_button.className = 'vote_down_off'
counter_element.innerText = current_counter
like_button.className = 'vote_up_on'
}
// if dislike is not checked
else {
if (like_button.className == 'vote_up_off') {
like_button.className = "vote_up_on"
current_counter += 1;
counter_element.innerText = current_counter
}
else {
like_button.className = "vote_up_off"
current_counter += -1;
counter_element.innerText = current_counter
}
}
}
function dislike_function(answer_id) {
var like_button = document.getElementById('like-'+answer_id);
var dislike_button = document.getElementById('dislike-'+answer_id);
var counter_element = document.getElementById('counter-'+answer_id);
let current_counter = parseInt(counter_element.innerText);
//check if like is on(true) or off(false)
let like_state = false
if (like_button.className == "vote_up_on") {
like_state = true
}
else {
like_state = false
}
//if like is checked
if (like_state) {
console.log('это тру лайк (лайк нажат)')
current_counter += -2;
like_button.className = 'vote_up_off'
counter_element.innerText = current_counter
dislike_button.className = "vote_down_on"
}
//if like is not checked
else {
if (dislike_button.className == 'vote_down_off') {
dislike_button.className = "vote_down_on"
current_counter += -1;
counter_element.innerText = current_counter
}
else {
dislike_button.className = "vote_down_off"
current_counter += 1;
counter_element.innerText = current_counter
}
}
}