(jQuery plugin: backstretch) Margin on the sides - javascript

I am using this great jQuery plugin to have the fullscreen backgound for my website.
This plugin currently fills the entire background on the screen, I was wondering if it is possible to give it a margin.
For instance I want to have a gap in the right side of the screen for 150px (so I can see the body background) and the rest of the page will be filled with backstretch.
I have played with _adjustBG function but I can't get this working.
Any helps will be appreciated.

Since the author of this plugin didn't make an option for margin, I'll tweak it for you.
Below is the modified _adjustBG() function that you may need.
Just open the file "jquery.backstretch.js" (the normal version, not the minimized) then replace the original _adjustBG() function (at the end of file) with this function.
function _adjustBG(fn) {
var rightMargin = 150; //--- edit the margin value here
try {
bgCSS = {left: 0, top: 0}
bgWidth = rootElement.width()-rightMargin;
bgHeight = bgWidth / imgRatio;
// Make adjustments based on image ratio
// Note: Offset code provided by Peter Baker (http://ptrbkr.com/). Thanks, Peter!
if(bgHeight >= rootElement.height()) {
bgOffset = (bgHeight - rootElement.height()) /2;
if(settings.centeredY) $.extend(bgCSS, {top: "-" + bgOffset + "px"});
} else {
bgHeight = rootElement.height();
bgWidth = bgHeight * imgRatio-rightMargin;
bgOffset = (bgWidth - rootElement.width()) / 2;
if(settings.centeredX) $.extend(bgCSS, {left: "-" + bgOffset + "px"});
}
$("#backstretch, #backstretch img:last").width( bgWidth ).height( bgHeight )
.filter("img").css(bgCSS);
} catch(err) {
// IE7 seems to trigger _adjustBG before the image is loaded.
// This try/catch block is a hack to let it fail gracefully.
}
// Executed the passed in function, if necessary
if (typeof fn == "function") fn();
}

Update:
By poking around w/ console, I found that if you subtract 150 from the width of the background-image, it will, by default, give you a margin on the right. You may want to adjust the height so your image scales, but, maybe something like this to run in $(document).ready():
var $bg = $('#backstretch');
var newImgWidth = $bg.width() - 150;
$bg.css('width', newImgWidth);

If IE6 is no issue, you can try to put the following in your stylesheet:
#backstretch{
width: auto !important;
right: 150px;
}
I tried this on the backstretch homepage and it worked as I would expect. As I am not totally familiar with this plugin please feel free to correct me.

Related

Position fixed, but scroll on <body>

I have this situation:
my website, which I am creating, has a left sidebar, which must be set to height 100%, while scrolling the webpage, and the content inside it is definitely over 1000px height.
because of the height of the content, I get vertical scroll on this sidebar element, and when my content has enough content, I get another scroll for this section.
What I have to do is to, somehow, transfer, scroll from the "fixed" element to the main page scroll...
I hope that you can understand me...
I hope that this screenshot, can also help you to understand what I ask:
link
Thank you in advance for you answers.
Your question got me interested, so I gave it a try.
You could have your sidebar set up like so:
#sidebar{
position:fixed;
min-height:100%;
top:0;
left:0;
/* ... */
}
Now, to make it scroll, we can play with its margin-top css property:
If we scroll down, we decrement it unless we scrolled past its
height.
If we scroll up, we increment it unless it's above zero.
I created a ScrollingSidebar class with 2 functions in order to deal with that:
// ScrollingSidebar class
// Define some variables and bind events
function ScrollingSidebar(el){
this.sidebar = el;
var that = this;
that.updateVariables();
document.addEventListener('scroll',function(){that.scrollSidebar();});
window.addEventListener('resize',function(){that.updateVariables();});
}
// Updates variables used for calculation
ScrollingSidebar.prototype.updateVariables = function(){
this.height = parseInt( getComputedStyle(this.sidebar).height );
document.body.style.minHeight = this.height + 'px';
this.winHeight = parseInt( window.innerHeight );
this.previousScrollPos = Math.floor( document.body.scrollTop ||
document.documentElement.scrollTop ||
document.body.parentNode.scrollTop
);
this.scrollSidebar();
};
// Updates the sidebar's margin-top
ScrollingSidebar.prototype.scrollSidebar = function(){
var curScrollPos = Math.floor( document.body.scrollTop ||
document.documentElement.scrollTop ||
document.body.parentNode.scrollTop
);
if(this.previousScrollPos < curScrollPos){
this.sidebar.style.marginTop = - Math.min(-parseInt( getComputedStyle(this.sidebar).marginTop ) + (curScrollPos - this.previousScrollPos),
this.height-this.winHeight) + 'px';
} else {
this.sidebar.style.marginTop = Math.min(0,parseInt( getComputedStyle(this.sidebar).marginTop ) + this.previousScrollPos-curScrollPos) + 'px';
}
this.previousScrollPos = curScrollPos;
};
You can use it like so:
// Create an instance of ScrollingSidebar
var sidebar = document.getElementById('sidebar');
var x = new ScrollingSidebar(sidebar);
JS Fiddle Demo (with a small amount of content)
JS Fiddle Demo (with a lot of content)
Note: I did not take the time to comment my code very well, but if you have any question about it or any problem with it, feel free to ask.
If your website is responsive and you don't want this method to be used on small screens, you might want to consider using a condition to disable it.

how to center and make various images sizes fit in a container

I'm using bxslider to have a carousel of images. The thing is though, the images it receives to display are of somewhat unpredictable sizes. The container size is 243x243. And we know that no image will have a side smaller than 243. So...I'd like to center the image in the container. And either zoom in until the shorter of the two dimensions (L vs W) fills the container at 243, and the longer dimension overflow is hidden.
For the images I'm working with, doing this will be perfect for getting the important details of the picture in the frame.
But I'm having trouble...
I've tried the following to center the picture in the frame:
jQuery(".bx-container").each(function() {
var img_w = jQuery(this).children("img").width();
var img_h = jQuery(this).children("img").height();
var pos_top = (img_h - containerHeight) / 2;
var pos_left = (img_w - containerWidth) / 2;
var pos_top = (243 - img_h) / 2;
var pos_left = (243 - img_w) / 2;
jQuery(this).children("img").css({
'top' : pos_top + 'px',
'left' : pos_left + 'px'
});
});
And I've tried this to position not square images into the frame:
jQuery(".bx-container").each(function(){
var refRatio = 1;
var imgH = jQuery(this).children("img").height();
var imgW = jQuery(this).children("img").width();
if ( (imgW/imgH) < refRatio ) {
jQuery(this).addClass("bx-portrait");
} else {
jQuery(this).addClass("bx-landscape");
}
});
});
I've messed with both scripts and the css but I just can't seem to get it work. It either centers but doesn't resize right. Or resizes but centers wrong. Or does both wrong.
Here's the jsfiddle: http://jsfiddle.net/vgJ9X/298/
Could someone help me out?
Thanks!
EDIT:
New jsfiddle...the portrait ones work right. The landscape images still squish. :(
http://jsfiddle.net/vgJ9X/307/
EDIT:
I THINK it has something to do with relatively positioned elements not being allowed to overlap. Trying to find a fix. If anyone knows, edit the last fiddle I posted.
jQuery(".bx-container img").each(function () {
var w = jQuery(this).width();
var h = jQuery(this).height();
if (w > h) $(this).addClass('bx-landscape');
else $(this).addClass('bx-portrait');
});
Check this Updated JSFiddle
Update
jQuery(".bx-container img").each(function () {
var w = jQuery(this).width();
var h = jQuery(this).height();
if (w > h){
$(this).addClass('bx-landscape');
var trans= -243/2;
$(this).css('-webkit-transform','translateZ('+trans+'px)');
}
else if(h > w){
$(this).addClass('bx-portrait');
var trans= -243/2;
$(this).css('-webkit-transform','translateY('+trans+'px)');
}
});
check this JSFiddle
Update of Update
Found the issue with landscape, the plugin is setting max-width:100%; overriding it with max-width:none; fixes the issue...
Update Of Updated Fiddle
Try this:
img{
position:relative;
height:100%;
width:300px;
}
Simple an clean.
Demo: http://jsfiddle.net/vgJ9X/302/
I did a couple things to your jsfiddle.
First I changed the order of your resize and center functions, so the resize comes first. This way, the smaller images get resized, then centered. I also uncommented the first portion of your code.
You also had a couple of errors in your css. There was an extra closing bracket after img style declaration. Your .bx-portrait img and .bx-landscape img declarations were set to 100%px;.
Update:
Change the css in your two .bx classes to:
.bx-portrait img {
height: 100%;
width: auto;
}
.bx-landscape img {
height: auto;
width: 100%;
}
And add a clearfix to your ul:
.bxslider:after {
content: '';
clear: both;
display: table;
padding: 0;
margin: 0;
}
The height is clipping because .bx-viewport has a set height of 243px but also has a 5px border, which makes the actual internal height 233px. You'll need to make the height 253px to account for the 10px of border. This is why they don't look centered vertically.
DEMO
Why don't you just use background images instead and center them. Here is a demo from your original code
http://jsfiddle.net/8y8df/
If you want to show the full size image, just remove the background-size:contain; from the css.

jQuery animation affects content below (Chrome)

I've create an affect that runs when a row of icons are visible on screen.
The animation is essentially changing the padding of a div, giving the effect of a pulse from the icons.
It works perfectly in every browser except Chrome (surprisingly!). Chrome for some reason wobbles the text under each icon while it animates. I used padding in the hopes that it would only affect the content within the div (using the box-sizing: border-box model).
I did write a fix for it which works in Chrome but then breaks the layout in Safari.
So I'm not sure if I can fix the wobble in Chrome or if I can alter my fix to help Safari out.
Here's the link to the page as it is at the moment, without the jQuery fix. It's in the JS file but commented out.
Here's the code that runs the animation, the fix is in here, just commented out:
$('.wrapper').scroll(function(e) {
var tTop = target.offset().top;
var tTopOffset = tTop+target.height();
if( tTop < height ) {
if (flag) {
targetDiv.animate({
opacity: 1
}, 500);
targetDiv.each(function(i){
// FIX breaks on safari, but fixes issue in Chrome...
// targetDiv.css('height', targetDivHeight);
$(this).delay((i++) * 900).animate({
padding: '0em'
}, 400);
$(this).animate({
padding: '0.5em'
}, 400);
});
flag = false
}
} else {
targetDiv.css('opacity', '0');
flag = true;
}
});
I think it is because you didn't specified the width and height of the element you are trying to animate. border-box doesn't just ignore padding value, it needs width and height value that includes padding and border. Using transform:scale could be nice either as commented above, but IMHO it is a bit tricky to achieve with .animate() and has less browser support.
Try this in console and try modify your code. I tried and it works well in the latest Safari and Chrome. (should use .outerHeight() to get correct value, since you use padding value to animate)
$ = jQuery;
var targetDiv = $('.icon-img-div');
var targetDivHeight = $('.icon-img-div').outerHeight();
var targetDivWidth = $('.icon-img-div').outerWidth();
targetDiv.each(function (i) {
// this breaks on safari, but fixes issue in Chrome...
targetDiv.css({
height: targetDivHeight,
width: targetDivWidth
});
$(this).delay((i++) * 900).animate({
padding: '0em'
}, 400);
$(this).animate({
padding: '0.5em'
}, 400);
});

Is there any cross-browser javascript for making vh and vw units work

Note: Ok while I was typing this question I came across this
question which suggests to use #media query but was asked back in
2011...
As you know CSS3 introduces new Viewport-percentage length units, vh and vw, which I feel are really useful for a solid responsive layout, so my question is, is there any JavaScript/jQuery alternative for this? More over apart from using it for font sizes, is it safe to use for sizing elements? Like example
div {
height: 6vh;
width: 20vh; /* Note am using vh for both, do I need to use vw for width here? */
}
Update 5: .css(property) fix
Plugins like fancyBox use .css('margin-right') to fetch the right margin of an element and .css('margin-right', '12px') to set the right margin of an element. This was broken, because there was no check if props is a string and if there are multiple arguments given. Fixed it by checking if props is a string. If so and there is multiple arguments, arguments is rewritten into an object, otherwise parseProps( $.extend( {}, props ) ) is not used.
Update 4: Plugin for responsive layouts https://github.com/elclanrs/jquery.columns (in the works)
I gave this a (long) try. First here's the CSS example: http://jsbin.com/orajac/1/edit#css. (resize the output panel). Notice that the font-size doesn't work with viewport units, at least on latest Chrome.
And here's my attempt at doing this with jQuery. The jQuery demo which works with the font as well is at http://jsbin.com/izosuy/1/edit#javascript. Haven't tested it extensively but it seems to work with most properties since it's just converting the values to pixel and then by calling the plugin on window.resize it keeps updating.
Update: Updated code to work with many browsers. Test locally if you're using anything other than Chrome because jsBin acts a bit weird with window.resize.
Update 2: Extend native css method.
Update 3: Handle window.resize event inside of the plugin so the integration is now seamless.
The gist (to test locally): https://gist.github.com/4341016
/*
* CSS viewport units with jQuery
* http://www.w3.org/TR/css3-values/#viewport-relative-lengths
*/
;(function( $, window ){
var $win = $(window)
, _css = $.fn.css;
function viewportToPixel( val ) {
var percent = val.match(/[\d.]+/)[0] / 100
, unit = val.match(/[vwh]+/)[0];
return (unit == 'vh' ? $win.height() : $win.width()) * percent +'px';
}
function parseProps( props ) {
var p, prop;
for ( p in props ) {
prop = props[ p ];
if ( /[vwh]$/.test( prop ) ) {
props[ p ] = viewportToPixel( prop );
}
}
return props;
}
$.fn.css = function( props ) {
var self = this
, originalArguments = arguments
, update = function() {
if ( typeof props === 'string' || props instanceof String ) {
if (originalArguments.length > 1) {
var argumentsObject = {};
argumentsObject[originalArguments[0]] = originalArguments[1];
return _css.call(self, parseProps($.extend({}, argumentsObject)));
} else {
return _css.call( self, props );
}
} else {
return _css.call( self, parseProps( $.extend( {}, props ) ) );
}
};
$win.resize( update ).resize();
return update();
};
}( jQuery, window ));
// Usage:
$('div').css({
height: '50vh',
width: '50vw',
marginTop: '25vh',
marginLeft: '25vw',
fontSize: '10vw'
});
I am facing this issue with the Android 4.3 stock browser (doesn't support vw,vh, etc).
The way I solved this is using 'rem' as a font-size unit and dynamically changing the < html >'s font-size with javascript
function viewport() {
var e = window, a = 'inner';
if (!('innerWidth' in window )) {
a = 'client';
e = document.documentElement || document.body;
}
return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}
jQuery(window).resize(function(){
var vw = (viewport().width/100);
jQuery('html').css({
'font-size' : vw + 'px'
});
});
and in your css you can use 'rem' instead of px,ems,etc
.element {
font-size: 2.5rem; /* this is equivalent to 2.5vw */
}
Here's a demo of the code : http://jsfiddle.net/4ut3e/
I wrote small helper to deal with this problem. It's supported on all main browsers and uses jQuery.
Here it is:
SupportVhVw.js
function SupportVhVw() {
this.setVh = function(name, vh) {
jQuery(window).resize( function(event) {
scaleVh(name, vh);
});
scaleVh(name, vh);
}
this.setVw = function(name, vw) {
jQuery(window).resize( function(event) {
scaleVw(name, vw);
});
scaleVw(name, vw);
}
var scaleVw = function(name, vw) {
var scrWidth = jQuery(document).width();
var px = (scrWidth * vw) / 100;
var fontSize = jQuery(name).css('font-size', px + "px");
}
var scaleVh = function(name, vh) {
var scrHeight = jQuery(document).height();
var px = (scrHeight * vh) / 100;
var fontSize = jQuery(name).css('font-size', px + "px");
}
};
Simple example how to use it in HTML:
<head>
<title>Example</title>
<!-- Import all libraries -->
<script type="text/javascript" src="js/libs/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="js/libs/SupportVhVw.js"></script>
</head>
<body>
<div id="textOne">Example text one (vh5)</div>
<div id="textTwo">Example text two (vw3)</div>
<div id="textThree" class="textMain">Example text three (vh4)</div>
<div id="textFour" class="textMain">Example text four (vh4)</div>
<script type="text/javascript">
// Init object
var supportVhVw = new SupportVhVw();
// Scale all texts
supportVhVw.setVh("#textOne", 5);
supportVhVw.setVw("#textTwo", 3);
supportVhVw.setVh(".textMain", 4);
</script>
</body>
It's available on GitHub:
https://github.com/kgadzinowski/Support-Css-Vh-Vw
Example on JSFiddle:
http://jsfiddle.net/5MMWJ/2/
Vminpoly is the only polyfill I know of — it's under develpment but works as of this post. There are static polyfills as part of the Jquery Columns and -prefix-free projects as well.
I've just made a very ugly, but perfectly working workaround for this WITH PURE CSS (no JS needed).
I came across a CSS stylesheet full of 'vw' declarations (also for heights and top/bottom properties) that needed to be rewritten for native Android Browser (which in versions 4.3 and below does NOT support 'vw' units).
Instead of rewriting everything to percentages, that are relative to parent's width (so the deeper in DOM, the most complicated calculations), which would give me a headache even before I would reach the first { height: Xvw } declaration, I generated myself the following stylesheet:
http://splendige.pl/vw2rem.css
I guess you're all familiar with 'em' units (if not: http://www.w3schools.com/cssref/css_units.asp). After some testing I discovered that old Android Browsers (as well as all the others) perfectly support the 'rem' units, which work the same as 'em', but are relative to the ROOT element font-size declaration (in most cases, the html tag).
So the easiest way to make this work was to declare the font-size for html tag that is equal to 1% of the viewport's width, e.g. 19.2px for 1920px viewport and use a lot of media queries for the whole 1920-320px range. This way I made the 'rem' unit equal to 'vw' in all resolutions (step is 10px, but you can even try declaring html{font-size} for every 1px). Then I just batch-replaced 'vw' with 'rem' and admired the working layout on Android 4.3 native browser.
Whatsmore, you can then redeclare the font-size even for the whole body tag (in whatever units you want: px, em, pt, etc.) and it does NOT affect the 'rem' equality to 'vw' in the whole stylesheet.
Hope this helps. I know it looks kinda silly, but works like a charm. Remember: if something looks stupid, but works, it is not stupid :)
"jquery.columns" is so far the best solutions.
https://github.com/elclanrs/jquery.columns
You only need 2 lines of codes to turn "vh" into a "all-browser scale".
Declare a class in html:
<img src="example.jpg" class="width50vh" />
Then in javascript:
$('.width50vh').css({width: '50vw'});
The simplest and most elegant solution I have found is to simply make a div that has height: 1vh; and width: 1vw; and when the page loads grab those values as pixels with getBoundingClientRect(). then add a listener to the document to listen for screen resizing and update the size when screen is resized.
I save the value in pixels of the vh and vw and then whenever I need to use vh i would just say 100 * vh which would give me 100vh.
Here is a code snippet on it's implementation, my answer is in vanilla js, no need for jquery.
function getViewportUnits(){
const placeholder = document.getElementById("placeholder");
const vh = placeholder.getBoundingClientRect().height;
const vw = placeholder.getBoundingClientRect().width;
console.log({vh: vh, vw: vw});
}
#placeholder{
background: red;
height: 1vh;
width: 1vw;
}
<body onload="getViewportUnits()">
<div id="placeholder"></div>
I've published a tiny lib that eases viewport-relative dimensions usage. Keep in mind it's not a polyfill, so it requires that you apply classes on the elements you want to resize. For instance, <div class="vh10 vw30">hello</div> will fill 10% of the height and 30% of the width.
Check it out: https://github.com/joaocunha/v-unit

Animation starts moving out of position after some time

I am trying to create a sort of slideshow animation. I have the codes here: jsFiddle.
These tablets would rotate around.
The problem is that, at random times, the animation will move out of line. The wrong tablets undergo wrong animations. Here are the screenshots:
And this is how it looks like when the animations goes wrong
The main problem is I don't understand why the animation would go wrong random times. In my computer it will run properly for hours, but in other cases (especially on Safari).
You could store the expected final css values for each animated el and then in the animate callback set these values, so for each animated el something like
var el = $(selector);
el.data("finalCSS", { your expected final CSS values })
$("selector").animate({animation properties}, function() {
el.css(el.data("finalCSS")).data("finalCSS", undefined);
})
This doesn't help with figuring out why it's happening (but I can't recreate the issue myself), but provides a failsafe to make sure the layout doesn't break;
I believe this happens when you try to animate before the previous animation has ended. Use jQuery stop() just before you animate. For example:
$('#animatingDiv').stop(false, true).animate({height:300}, 200, callback);
The first param(false) will empty the animation queue on that element and the second param(true) will jumps to the end of current animation before starting a new animation.
You can do this with far less code and far fewer headaches.
1. Store your tablet position attributes in classes
.tablet1{
height:100px;
width:140px;
margin-left:-540px;
top: 200px;
z-index:10;
}
2. Use a general function to handle all your transitions.
JQuery UI will do all the work for you if you use switchClass
switchTabletsRight = function(){
var i, next, max = 5;
for(i = 1; i <= max; i++){
next = (i < max)? i + 1 : 1;
$(".tablet" + i).switchClass("tablet" + i, "tablet" + next);
}
};​
Here's the JSfiddle proof of concept: http://jsfiddle.net/nRHag/4/
You are setting CSS positions to decimal values.
img_w = $("#tablet"+num+" img").width();
img_w = img_w *140 / 600;
img_h = $("#tablet"+num+" img").height();
img_h = img_h *140 /600;
...
var new_width = $(this).width() * 140 / 600;
$(this).css('width', new_width);
var new_height = $(this).height() * 140 / 600;
$(this).css('height', new_height);
Your division could be cause decimal results which have different effects in different browsers. Sub pixel CSS positioning may be creating your unintended errors.

Categories