Full screen background image minus flexible top-nav bar - javascript

This is my first post here and I haven't been able to find the answer to my question.
I am building a page and I want a picture to fill the entire screen, from the bottom of the top-nav bar (menu etc..) to the bottom of the screen. Only issue I have... the bar is responsive : it's taller on very large screen and much smaller on mobiles, which of course impacts my background image differently on different screens.
Here's my css :
.backgroundimage{
background-image: url(https://file...);
background-repeat: no-repeat;
background-size: cover;
width: 100%;
min-height: 100vh;
background-position: center center;
position: relative;
}
</style>
So I've tried multiples things for hours, playing around with the "vh" property.
For example :
min-height:calc(100vh - 17vh)
That gives decent result on my laptop, but not on a larger screen. So I've been trying to find the fonction or class that represents the navHeight, but I can't find a proper way to do it and nothing is working so far. I've tried stuff like :
min-height:calc(100vh - $headerHeight)
And so on... This is a shopify store and I have no knowledge in js, which may explain why I'm struggling. Here's some js code that revolves around the header, but nowhere can I find a way to remove the height of the header. Any idea or direction to give me ? Thanks.
JS code (not in proper order):
theme.headerNav = (function() {
var selectors = {
siteNav: '#SiteNav',
siteNavCompressed: '#SiteNavCompressed',
siteNavParent: '#SiteNavParent',
siteNavItem: '.site-nav__item',
stickyNavWrapper: '#StickNavWrapper',
stickyNav: '#StickyNav'
};
function init() {
sizeNav();
initMegaNavs();
initHeaderSearch();
$(window).on('resize.headernav', $.debounce(250, sizeNav));
}
window.Meganav = (function() {
var Meganav = function(options) {
this.cache = {
$document: $(document),
$page: $('.page-element')
};
var defaults = {
$meganavs: $('.meganav'),
$megaNav: $('.meganav__nav'),
$meganavToggle: $('.meganav-toggle'),
$meganavDropdownContainers: $('.site-nav__dropdown-container'),
$meganavToggleThirdLevel: $('.meganav__link-toggle'),
$meganavLinkSecondLevel: $('.meganav__link--second-level'),
$meganavLinkThirdLevel: $('.meganav__link--third-level'),
$meganavDropdownThirdLevel: $('.site-nav__dropdown--third-level'),
isOpen: false,
preventDuplicates: false,
closeOnPageClick: false,
closeThirdLevelOnBlur: false,
activeClass: 'meganav--active',
drawerClass: 'meganav--drawer',
meganavDropdown: '.site-nav__dropdown',
meganavLinkClass: 'meganav__link',
drawerToggleClass: 'drawer__nav-toggle-btn',
drawerNavItem: '.drawer__nav-item',
navCollectionClass: 'meganav__nav--collection',
secondLevelClass: 'meganav__link--second-level',
thirdLevelClass: 'meganav__link-toggle',
thirdLevelContainerClass: 'site-nav__dropdown--third-level',
noAnimationClass: 'meganav--no-animation'
};
theme.HeaderSection = (function() {
function Header() {
theme.stickyHeader.init();
theme.headerNav.init();
theme.Notify = new window.Notify();
theme.NavDrawer = new window.Drawers('NavDrawer', 'left');
drawerSearch();
}

Related

Buggy snap-scrolling while DOM changes

I have a feed of photos that are scrolled vertically in my app and I'm using snap scroll.
The feed is a virtual scroller, i.e. - only X elements are actually on the DOM, and elements above and below are removed/inserted as needed.
Important to note that this is a mobile web app.
However, when I scroll and DOM changes happen while scrolling, I'm getting the following buggy behaviors:
The previous photo flickers while transitioning to the next photo
The feed scrolls to the previously seen photo (doesn't repro 100% of the times)
I created a simulation in Codepen to repro the issues; a div is added to the DOM every 0.5secs, and trying to scroll while on mobile view repros both issues - [link to Codepen], please use a mobile view.
HTML:
<div class="snap-scroll-container"></div>
JS:
const snapScrollContainer = document.querySelector(".snap-scroll-container");
[
"https://media.istockphoto.com/photos/gray-british-cat-kitten-picture-id1086004080?k=20&m=1086004080&s=612x612&w=0&h=tvQKNjBGIsfCmUPR8YVJYfjLrTZ9JINbisKRjMj87IY=",
"https://images.unsplash.com/photo-1595433707802-6b2626ef1c91?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=880&q=80",
"https://images.unsplash.com/photo-1592194996308-7b43878e84a6?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80",
"https://images.unsplash.com/photo-1574144611937-0df059b5ef3e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80",
"https://www.warrenphotographic.co.uk/photography/bigs/08483-Ginger-kitten-portrait.jpg",
"https://img.freepik.com/premium-photo/kitten-portrait-beautiful-fluffy-gray-kitten-cat-animal-baby-british-blue-kitten-with-big-eyes-sits-beige-plaid-looking-camera-blue-background_221542-1665.jpg?w=740",
"https://libreshot.com/wp-content/uploads/2018/02/cute-kitten-portrait-861x1292.jpg",
"https://www.warrenphotographic.co.uk/photography/bigs/35147-Portrait-of-tabby-kitten-8-weeks-old.jpg",
].forEach((src) => {
const image = document.createElement("img");
const div = document.createElement("div");
div.setAttribute("class", "snap-scroll-child");
image.setAttribute("src", src);
div.appendChild(image);
snapScrollContainer.appendChild(div);
});
const addEmptyDiv = () => {
const div = document.createElement("div");
div.innerHTML = "bla";
snapScrollContainer.appendChild(div);
}
setInterval(addEmptyDiv, 500);
CSS:
body {
margin: 0;
padding: 0;
}
.snap-scroll-container {
scroll-snap-type: y mandatory;
height: 100vh;
overflow-y: scroll;
}
.snap-scroll-child {
scroll-snap-stop: always;
scroll-snap-align: end;
}
img {
object-fit: cover;
height: 100vh;
width: 100vw;
}
Unfortunately giving up on the virtual scroller is not an option as the perf hit will be large.
Going over SO and docs (including docs about restoring scroll position automatically after DOM changes), I couldn't find any plausible solution, other than maybe:
Implementing snap scroll in JS (I would rather not)
Deferring DOM changes until scrolling is complete (not optimal)
[Link to GIF showing the issue]

Compare images with JS

I'm currently working on a site and there will be an image in the background with the following dimensions: 100vw, 100vh – But of course I want the page to be responsive and this is my plan:
It is ok, to distort this background-image a bit, but I should never be distorted to much, so I want to create multiple different images, for different aspect-ratios and sizes and whenever the page is being loaded, or resized, I would like to have a script that looks at the viewport: aspect-ratio and size, then looks at all the images and finds the one that is most similar to the viewport and then sets that image as the background-images of: div class="bg-overlay"
This is what I have so far:
HTML:
<div class="bg-overlay"></div>
CSS:
bg-overlay {
position: fixed;
width: 100vw;
height: 100vh;
background-image: url("resources/Test-Screens/RZ_BG_1920x1080_16-9.png");
background-size: 100vw 100vh;
}
JS:
var bgOverlayDiv = document.querySelector(".bg-overlay");
// Image-Library START
var bg_1280x720 = {
name: 'RZ_BG_1280x720_16-9.png',
width: '1280',
height: '720'
};
bg_1280x720.ratio = bg_1280x720.width / bg_1280x720.height;
var bg_1920x1080 = {
name: 'RZ_BG_1920x1080_16-9.png',
width: '1920',
height: '1080'
};
bg_1920x1080.ratio = bg_1920x1080.width / bg_1920x1080.height;
var bg_3840x2160 = {
name: 'RZ_BG_3840x2160_16-9.png',
width: '3840',
height: '2160'
};
bg_3840x2160.ratio = bg_3840x2160.width / bg_3840x2160.height;
var bg_4000x4000 = {
name: 'RZ_BG_4000x4000_1-1.png',
width: '4000',
height: '4000'
};
bg_4000x4000.ratio = bg_4000x4000.width / bg_4000x4000.height;
var bg_2000x2000 = {
name: 'RZ_BG_2000x2000_1-1.png',
width: '2000',
height: '2000'
};
bg_2000x2000.ratio = bg_2000x2000.width / bg_2000x2000.height;
var bg_1000x1000 = {
name: 'RZ_BG_1000x1000_1-1.png',
width: '1000',
height: '1000'
};
bg_1000x1000.ratio = bg_1000x1000.width / bg_1000x1000.height;
var bg_1080x1920 = {
name: 'RZ_BG_1080x1920_9-16.png',
width: '1080',
height: '1920'
};
bg_1080x1920.ratio = bg_1080x1920.width / bg_1080x1920.height;
// Image-Library END
var viewportRatio = undefined;
var chosenImage = undefined;
function changeBgOverlay() {
// Calculate viewport aspect-ratio. START
viewportRatio = window.innerWidth / window.innerHeight;
console.log(viewportRatio);
// Calculate viewport aspect-ratio. END
chosenImage = bg_1080x1920; // Add: Choose most suitable image.
bgOverlayDiv.style.backgroundImage = "url('resources/Test-Screens/" + chosenImage.name + "')";
}
changeBgOverlay();
window.addEventListener('resize', changeBgOverlay);
^- I can't really share a fiddle, because there are images involved, I hope it's clear what this script is doing, if not, please tell me, I can also just send someone the folder-structure that I have on my computer, with all the images, but this is basically what's happening right now:
First I'm creating multiple objects for every image in my folder-structure, these objects have properties: name, width, height, (aspact-)ratio – Then I calculate the viewport-aspect-ratio (var viewportRatio) – Then there is a line that, right now, says: chosenImage = bg_1080x1920; (This is where the script should look for the most suitable image, right now, I'm just manually telling it to use the object called: bg_1080x1920) – Then it replaces the image.
Screenshot of the folder containing the images:
I already played around with this for a while, but I don't really now how to do this, I would very much appreciate any sort of input. Thank You! – Simon

Fading Banner Using `background:url()`

I have a banner enclosed in a div tag that contains my banner. I would like to get the banner to fade to the next image but unsure how to achieve the fading effect. I have tried using jQuery fadeIn() but it failed.
The reason why I need to use the background: url() is because I want this banner image to resize pleasantly when the browser gets resized. I am not sure if this is the best way of approaching my problem.
EDIT - My current code does swap the images in the banner, but does not apply the fadeIn() effect. The console does not report any errors.
CSS:
header div#banner {
background: url(../image/banner/00.jpg) no-repeat center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
height: 300px;
}
JavaScript:
var bannerImages = new Array();
var bannerCounter = 0;
function run() {
loadBannerImages();
runBannerTimer();
}
function loadBannerImages() {
var filePath = "image/banner/";
bannerImages[0] = filePath + "00.jpg";
bannerImages[1] = filePath + "01.jpg";
bannerImages[2] = filePath + "02.jpg";
bannerImages[3] = filePath + "03.jpg";
bannerImages[4] = filePath + "04.jpg";
}
function runBannerTimer() {
var t=setTimeout("swapBannerImage()",2000);
}
function swapBannerImage() {
$('#banner').fadeIn(1000, function() {
$('#banner').css('background', 'url(' + bannerImages[bannerCounter] + ') no-repeat center');
});
bannerCounter++;
if (bannerCounter >= bannerImages.length) {
bannerCounter = 0;
}
runBannerTimer();
}
Your setTimeout isn't correct; try the following instead:
function runBannerTimer() {
var t=setTimeout(function(){
swapBannerImage()
},2000);
}
EDIT
Here is the updated Banner Swap function:
function swapBannerImage() {
$('#banner').fadeOut('slow', function(){
$('#banner').css('background', 'url(' + bannerImages[bannerCounter] + ') no-repeat center').fadeIn('slow');
});
bannerCounter++;
if (bannerCounter >= bannerImages.length) {
bannerCounter = 0;
}
runBannerTimer();
}
Updated Demo Here
You could use multiple divs -- one per image -- and fade them in/out. The divs could still use the css background like you want, you'll just need to absolutely position them, so that they appear one on top of another. However, to get absolutely positioned divs to resize with the parent div (ie to get the "pleasant" resizing effect), you have to set up the css like so:
header div#banner {
... /* your background stuff here */
position: absolute;
left: 0;
right: 0;
height: 300px;
}
Note that you'll assign both left and right, which would make it take up the entire width of the parent. And, make sure that the parent has position:relative.

How to make a preview of DIV in another DIV?

I am making an application or a site in html/css/javascript that will allow me to create slides, add some text, image maybe change color and styles to every slide and than launch it as a whole presentation.
So far I have managed to make a really easy layout :
http://sandbox.padsbanger.pl/ss/
My question is:
How can I make a dynamic preview of a div on sidebar and a full view of slide on the right ? This would allow me to switch between the diffrent slides and make changes to them.
Thanks in advance :)
EDIT: For this project I am not allowed to use PHP.
EDIT 2:
I am not bothering about storing the data about slides somewhere in db. The idea of this app it to make a presentation consistig of a few slides and then launch it full screen view as a presentation.
Well, you could do something like this:
.slajd * {
zoom: 0.25;
-moz-transform: scale(0.25);
-moz-transform-origin: 0 0;
-o-transform: scale(0.25);
-o-transform-origin: 0 0;
-webkit-transform: scale(0.25);
-webkit-transform-origin: 0 0;
}
That would shrink all the content in the left 'preview' panes to 1/4 size. Then, when you click one just copy the innerHTML to the right pane and since it won't have the zoom/scale styles it will be full size.
As for the connecting - this will make all slides clickable. I suggest you add this to a document.ready block somewhere in the HEAD.
$('#leftcolumn').on('click', '.slajd', function() {
$('#rightcolumn').html($(this).html());
});
If you want to show the exact contents of the left sidebar in the main content area you can read the contents of the current sidebar using $this then use .html to read the content.
Take a look at Google Docs, slide/presentation as an example.
They basically size everything tiny in the left box which is just what's in the right.
First, you need to save all of the design parameters in a data structure, for example:
var design =
[
{
type : "background-image",
params :
{
url: "/images/snow.png"
}
},
{
type : "image",
params :
{
x : 100,
y : 300,
width : 100,
height : 100,
url: "/images/tree.png"
}
},
{
type : "text",
params :
{
x : 100,
y : 300,
text : "Happy XMAS!",
font :
{
size : 20
family: arial;
}
}
},
];
Here you have a background image, some text and a regular image.
The size parameters will be used normally on the regular sized slide but you will have to divide those parameters by the size ratio of the large slide & the small one for example:
if the large slide is 400x400 and the small one is 100x100 do this:
largeWidth = 400;
largeHeight = 400;
smallWidth = 100;
smallHeight = 100;
xRatio = Math.round( largeWidth / smallWidth );
yRatio = Math.round( largeHeight / smallHeight );
Now, when you draw the thumbnail slide you need to divide the coordinates of the large one (which are specified in the data structure by the x & y ratios).

My jquery loading overlay doesn't show up every

For whatever reason, my jquery loading overlay doesn't load at all under any circumstance even though the same code was working just days ago. Well, not the exact same code. I have been trying to get the overlay to resize with the window, and I have been trying different things, but I don't understand what I did that caused the overlay to never even show up? Here is the code that should attach to the overlay to the correct div...
function MRNSearchInternals()
{
//debugger;
var form = $("#MRNSearch");
$div = $("#TabView1");
var srlzdform = form.serialize();
var PopID = <% =PopID %>;
var options = [];
var $url = $("#target").attr("action");
$('<div id="overlay">').css({
position: 'absolute',
opacity: 0.2,
top : $div.offset().top,
left : $div.offset().left,
width : $div.offset().width,
height : $div.outerHeight(),
background: 'blue url(<%=Url.Content("~/images/ajax-loader.gif")%>) no-repeat center'
}).hide().appendTo($div);
$("#overlay").fadeIn();
$.post('<%:Url.Action("SearchByMRN", "PatientACO")%>', srlzdform, function (data)
{
DisplayDemographicSearch(data);
$("#overlay").fadeOut();
});
}
Notice how I create the div. I give it an id, and then I call it's css atribute. From there I set all the css attributes. I then attempt to call fadeIn, and fadeOut after the ajax call. Any body have any idea why this isn't working? Any help would be great.
Some More clarification
Also notice how I chose the div to overlay. I get a div id from my dom
$div = $("#TabView1");
Also, I looked the source, and I do have that particular div in there. So that is not the problem. Somehow or the other, it simply isn't showing up.
UPDATE: The DOM I get
Below is what is produced from the jquery code. It appears as though everything is being created fine. Note also, that display is set to none. That is what I would expect since I have the overlay fade out. My question is why does it never show up.
<div class="TabView" id="TabView1">
<div class="Tabs">...</Tabs>
<div class="Pages">
<div id="overlay" style="left: 114px; top: 205px; height: 452px; display: none; position: absolute; opacity: 0.2; background-image: url("/images/ajax-loader.gif"); background-attachment: scroll; background-repeat: no-repeat; background-position-x: center; background-position-y: center; background-size: auto; background-origin: padding-box; background-clip: border-box; background-color: blue;"/>
</div>
Well, the better way to create the overlay div would be
$('<div/>', {
id: 'overlay'
})
Does that solve the problem? Otherwise, the ID might not be created, or does it?
Update for the edit from your post: the "width" attribute is not set on the created overlay. What happens if that is added and set to e.g. 100px? It seems like there is something wrong with the setting of the width attribute (or the getting of the width attribute of $div).
Is this code called more than once? If so, are you removing #overlay somewhere?
Calling this code multiple times would create duplicate #overlay dom nodes which is a no-no and could explain why it doesn't work sometimes.
To remove it, change:
$("#overlay").fadeOut();
to:
$("#overlay").fadeOut('slow', function () {
$("#overlay").remove();
});
Your selector doesn't look right.
I would try:
$('#overlay').css. . . .
function MRNSearchInternals()
{
//debugger;
var form = $("#MRNSearch");
$div = $("#TabView1");
var srlzdform = form.serialize();
var PopID = <% =PopID %>;
var options = [];
var $url = $("#target").attr("action");
$('<div id="overlay">').css({
position: 'absolute',
opacity: 0.2,
top : $div.offset().top,
left : $div.offset().left,
width : $div.offset().width, //<- The problem is right here should be $div.width
height : $div.outerHeight(),
background: 'grey url(<%=Url.Content("~/images/ajax-loader.gif")%>) no-repeat center'
}).hide().appendTo($div);
$("#overlay").fadeIn();
$.post('<%:Url.Action("SearchByMRN", "PatientACO")%>', srlzdform, function (data)
{
DisplayDemographicSearch(data);
$("#overlay").fadeOut('slow', function () {
$("#overlay").remove();
});
});
}
Man. That was real hard to debugg. I wish Visual studio 2010 had better jquery debugging capability. Thankfully, the next version is supposed to be a better jquery debugger. But, the problem was the width attribute.

Categories