Safari gives wrong height() property - javascript

I have problem with Safari. Gives me wrong height property after using a .height() function. Only this one browser works wrong, others gets me correct height.
HTML + CSS:
.col-header-content {
width: 100%;
position: absolute;
top: 50%;
color: #fff;
text-align: center;
}
<div class="cat-col-wrapper">
<div class="cat-col-header">
<div class="col-header-content">
/* next content DOM with
width: 100%;
position: relative
float: left;
*/
</div>
</div>
</div>
JS FILE:
(function($) {
$(window).load(function(e) {
_E.Controller();
}
_E = {
Controller: function() {
$('.cat-col-wrapper').each(function(index, el) {
var headerContent = $(this).find('.col-header-content');
console.log(headerContent.height());
}
}
}
}(window.jQuery));
When real height of element is 185px, Safari gives me 584px.

.cat-col-header had a css transform property on .3s and when page was loading script first calculate height and then make transform to correct css width.
Example solution:
JS:
$(window).load(function(e) {
$('body').addClass('loaded');
});
$(document).ready(function(e) {
/* count what you want and watch out on Safari browser */
});
CSS:
body.loaded .cat-col-header {
transition: .3s;
}

Related

Smooth scrolling slider with play/pause button

I'm doing a project where I need a scrollable slider with play pause button like www.gap.com. I got this below code from W3C but not sure why multiple images are not showing fully. If I change the width value in CSS code, only first image portion scrolls but it totally ignores the 2nd image. Please anyone help me.
var speed=20 // speed of scroller
var step=3 // smoothness of movement
var StartActionText= "Scroll" // Text for start link
var StopActionText = "Pause" // Text for stop link
var x, scroll, divW, sText=""
function onclickIE(idAttr,handler,call){
if ((document.all)&&(document.getElementById)){idAttr[handler]="Javascript:"+call}
}
function addLink(id,call,txt){
var e=document.createElement('a')
e.setAttribute('href',call)
var linktext=document.createTextNode(txt)
e.appendChild(linktext)
document.getElementById(id).appendChild(e)
}
function getElementStyle() {
var elem = document.getElementById('scroller');
if (elem.currentStyle) {
return elem.currentStyle.overflow;
} else if (window.getComputedStyle) {
var compStyle = window.getComputedStyle(elem, '');
return compStyle.getPropertyValue("overflow");
}
return "";
}
function addControls(){
// test for CSS support first
// test for the overlow property value set in style element or external file
if (getElementStyle()=="hidden") {
var f=document.createElement('div');
f.setAttribute('id','controls');
document.getElementById('scroller').parentNode.appendChild(f);
addLink('controls','Javascript:clickAction(0)',StopActionText);
onclickIE(document.getElementById('controls').childNodes[0],"href",'clickAction(0)');
document.getElementById('controls').style.display='block';
}
}
function stopScroller(){clearTimeout(scroll)}
function setAction(callvalue,txt){
var c=document.getElementById('controls')
c.childNodes[0].setAttribute('href','Javascript:clickAction('+callvalue+')')
onclickIE(document.getElementById('controls').childNodes[0],"href",'clickAction('+callvalue+')')
c.childNodes[0].firstChild.nodeValue=txt
}
function clickAction(no){
switch(no) {
case 0:
stopScroller();
setAction(1,StartActionText);
break;
case 1:
startScroller();
setAction(0,StopActionText);
}
}
function startScroller(){
document.getElementById('tag').style.whiteSpace='nowrap'
var p=document.createElement('p')
p.id='testP'
p.style.fontSize='25%' //fix for mozilla. multiply by 4 before using
x-=step
if (document.getElementById('tag').className) p.className=document.getElementById('tag').className
p.appendChild(document.createTextNode(sText))
document.body.appendChild(p)
pw=p.offsetWidth
document.body.removeChild(p)
if (x<(pw*4)*-1){x=divW}
document.getElementById('tag').style.left=x+'px'
scroll=setTimeout('startScroller()',speed)
}
function initScroller(){
if (document.getElementById && document.createElement && document.body.appendChild) {
addControls();
divW=document.getElementById('scroller').offsetWidth;
x=divW;
document.getElementById('tag').style.position='relative';
document.getElementById('tag').style.left=divW+'px';
var ss=document.getElementById('tag').childNodes;
for (i=0;i<ss.length;i++) {sText+=ss[i].nodeValue+" "};
scroll=setTimeout('startScroller()',speed);
}
}
function addLoadEvent(func) {
if (!document.getElementById | !document.getElementsByTagName) return
var oldonload = window.onload
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload()
func()
}
}
}
addLoadEvent(initScroller)
body {font:1em verdana,sans-serif; color:#000; margin:0}
/* position:relative and overflow:hidden are required */
#scroller { position:relative; overflow:hidden; width:30em; border:1px solid #008080; }
/* add formatting for the scrolling text */
#tag { margin:2px 0; }
/* #testP must also contain all text-sizing properties of #tag */
#testP { visibility:hidden; position:absolute; white-space:nowrap; }
/* used as a page top marker and to limit width */
#top { width:350px; margin:auto; }
<div id="scroller">
<div id="tag">
<img src="https://picsum.photos/1500/600/?image=1"/>
<img src="https://picsum.photos/1500/600/?image=2"/>
</div>
</div>
I got a bit lost in the given JS, and wonder if it is necessary for this relatively simple task.
Here is a method using HTML and CSS for the continuous scrolling and with JS just for the pause/play part.
Because you want continuous scrolling with no gap or jump when the sequence of images goes back to the beginning you need two copies. The tag element is scrolled to the left by half of its width which means that the set of images overwrite themselves so giving a smooth effect.
The JS for the button uses the running value and toggles that.
.playpause {
top: 10%;
left: 10%;
position: absolute;
z-index: 1;
}
#scroller {
width: min(30em, 100vw);
height: min(20em, 100vh);
display: inline-block;
white-space: nowrap;
overflow: hidden;
position: relative;
}
#scroller #tag {
height: 100%;
animation: scroll 10s linear infinite;
animation-fill-mode: forwards;
display: inline-block;
font-size: 0;
}
#keyframes scroll {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
img {
height: 100%;
width: auto;
display: inline-block;
}
<div id="scroller">
<button class="playpause" onclick="document.querySelector('#tag').style.animationPlayState = (document.querySelector('#tag').style.animationPlayState != 'paused') ? 'paused' : 'running';">PLAY/PAUSE</button>
<div id="tag">
<img src="https://picsum.photos/1500/600/?image=1" />
<img src="https://picsum.photos/1500/600/?image=2" />
<!-- second copy of all the imaages -->
<img src="https://picsum.photos/1500/600/?image=1" />
<img src="https://picsum.photos/1500/600/?image=2" />
</div>
</div>
Observation: the site linked to in the question (gap) has a slightly unpleasant 'jump' half way through the images so I think they must be using a different method to achieve continuous scrolling.

How to animate the css zoom property

Is it possible to get a smooth transition for the css zoom property?
I googled a lot, but the results for the keywords "css" and "zoom" are always about transform and transition. So, I don't want to know how to do it with transform and scale and so on. Just with the css zoom property.
document.querySelector('div').addEventListener('click', function(e) {
e.target.classList.toggle('zoom');
});
div {
width: 50px;
height: 50px;
background: red;
cursor: pointer;
}
.zoom {
zoom: 200%;
}
<div>click me!</div>
Non-standard This feature is non-standard and is not on a standards
track. Do not use it on production sites facing the Web: it will not
work for every user. There may also be large incompatibilities between
implementations and the behavior may change in the future.
The non-standard zoom CSS property can be used to control the
magnification level of an element. transform: scale() should be used
instead of this property, if possible. However, unlike CSS Transforms,
zoom affects the layout size of the element.
MDN
So, you can use scale for this.
document.querySelector('div').addEventListener('click', function(e) {
e.target.classList.toggle('zoom');
});
div {
width: 50px;
height: 50px;
background: red;
cursor: pointer;
transition:.5s;
transform-origin:left top;
}
.zoom {
transform:scale(2);
}
<div>click me!</div>
function zoomIn(tg) {
let fr = 100;
setInterval(function() {
if(fr < 200) {
fr++;
tg.style.zoom = fr + "%";
};
}, 5);
}
function zoomOut(tg) {
let fr = 200;
setInterval(function() {
if(fr > 100) {
fr--;
tg.style.zoom = fr + "%";
};
}, 5);
}
document.querySelector('div').addEventListener('click', function(e) {
if(e.target.classList.contains('zoom')) {
e.target.classList.remove("zoom")
zoomOut(e.target);
} else {
e.target.classList.add("zoom");
zoomIn(e.target);
}
});
div {
width: 50px;
height: 50px;
background: red;
cursor: pointer;
transition: .5s;
}
<div>click me!</div>
You can use css transition, for your case:
.zoom {
transition: width 1s, height 1s;
}
Here all times that this width and height div changes will get 1 second

JavaScript on scroll to shrink logo AND menu bar

I'm working on a WordPress site, I have used the following JavaScript code to shrink the logo on scroll:
logo has id #logoid
CSS
.logoclass {width:100%;
transition: width 0.5s linear;}
.scroll {margin-top:-10px;
width:55%;
transition: width 0.5s linear;}
Javascript
<script type="text/javascript">
window.onscroll = () => {
const nav = document.querySelector('#logoid');
if(this.scrollY <= 250) nav.className = 'logoclass'; else nav.className =
'scroll';};
</script>
Now this works fine to simply shrink the image and restore size.
Now I have two problems:
Since I'm using WordPress plugins, there are many attributes applied
to the logo internally and are not in my .logoclass or in the
.scroll so these attributes get removed once I scroll and do not
get applied again. Is there a way to :
a) On scroll down ONLY change size while keeping other attributes
intact
b) On scroll up revert to initial settings completely (remove new
class)
My second question is, I want to also modify the menu bar size on scroll, but I cannot use the same code twice because it seems to only accept the code written last. Possibly because windows.onscroll gets added twice. Any way to incorporate both?
For #1, you should use the classList property to add or remove classes.
For #2, you should be able to add whatever changes you want in the same if statement.
window.onscroll = () => {
const nav = document.querySelector('#logoid');
const menu = document.querySelector('#menubar');
if (this.scrollY <= 250) {
nav.classList.remove('scroll');
menu.classList.remove('someclass');
} else {
nav.classList.add('scroll');
menu.classList.add('someclass');
}
};
.logoclass {
width: 100%;
transition: width 0.5s linear;
}
.scroll {
margin-top: -10px;
width: 55%;
transition: width 0.5s linear;
}
body {
height: 1000px;
}
#logoid {
position: absolute;
top: 0px;
background: red;
height: 25px;
}
<div id="logoid" class="logoclass"></div>
<div id="menubar" class="menuclass"></div>
If you add a global scroll class to your body tag you won't have to change your JavaScript if you want to change more things on scroll, only your CSS.
window.onscroll = () => {
const body = document.querySelector('body');
if (this.scrollY <= 250) {
body.classList.remove('scroll');
} else {
body.classList.add('scroll');
}
};
.logoclass {
width: 100%;
transition: width 0.5s linear;
}
.scroll .logoclass, .scroll .menuclass {
margin-top: -10px;
width: 55%;
transition: width 0.5s linear;
}
body {
height: 1000px;
}
#logoid {
position: absolute;
top: 0px;
background: red;
height: 25px;
}
<div id="logoid" class="logoclass"></div>
<div id="menubar" class="menuclass"></div>
If you wan't to run multiple functions on scroll you should use addEventListener.
window.addEventListener('scroll', function() {
doSomething();
});
window.addEventListener('scroll', function() {
doSomeOtherThing();
});

Animating height property :: HTML + CSS + JavaScript

I have noticed this 'issue' lately when trying some stuff.
Say I want to create a drop-down menu or an accordion.
This is my HTML:
<div class="wrapper" onclick="toggle()">
I want to be animated!
<div class="content">
Was I revealed in a timely fashion?
</div>
</div>
Stylesheets:
.wrapper {
background: red;
color: white;
height: auto;
padding: 12px;
transition: 2s height;
}
.content {
display: none;
}
.content.visible {
display: block;
}
JavaScript:
function toggle () {
var content = document.getElementsByClassName('content')[0];
var test = content.classList.contains('visible');
test ? content.classList.remove('visible') :
content.classList.add('visible');
}
I am trying to achieve a nice, smooth animation when we toggle the state of the content. Obviously this does not work. Anyone can explain to me why it does not work and how to fix it? Many thanks.
Link to the JSFiddle.
First things first, some CSS properties CANNOT be transitioned, display is one of them, additionally only discrete values can be transitioned, so height: auto cannot as well.
In your case the problem is with height: auto, while there are a few hacks for doing this, if you are just showing and hiding stuff, why not add, and use jQuery's toggle instead?
$(".content").toggle("slow");
jsFiddle
--EDIT (without jQuery)--
Because it's the auto that is giving us problems, we can use javascript to replace auto with a value in pixels and then use the css transition normally, if your content doesn't have a scroll, we can easily take that value from the scrollHeight property:
function toggle () {
var content = document.getElementsByClassName('content')[0];
var test = content.classList.contains('visible');
console.log(test);
if (test) {
content.classList.remove('visible')
content.style.height = "0px";
} else {
content.classList.add('visible');
content.style.height = content.scrollHeight + "px";
}
}
Css
.wrapper {
background: red;
color: white;
height: auto;
padding: 12px;
transition: 2s height;
}
.content {
height: 0px;
display: block;
transition: 2s height;
overflow: hidden;
} /* totally removed .content.visible */
jsFiddle

RoyalSlider's height is minimum on init in Safari

I am using enquire.js to set my RoyalSlider's height dynamically to the height of the element right next to it. This is working in Firefox, but in Safari on load, the height of the slider is the minimal height possible (so the height of the arrows). Only after I resize the window, the correct height is adapted.
enquire.register("screen and (max-width: 53.999em)", {
match : function() {
$('.slide').css('height', "10em");
}
}).register("screen and (min-width: 54em)", {
match : function() {
var height = $('.one:first').outerHeight(true) * 2;
$('.slide').css('height', height);
window.onresize = function() {
var height = $('.one:first').outerHeight(true) * 2;
$('.slide').css('height', height);
}
},
unmatch : function() {
$('.slide').css('height', "10em");
}
});
I tried to set a static height in CSS for the inital load, but the style is not adapted.
Got it working now with a solution just using CSS :)
See this: https://stackoverflow.com/a/6615994/1478344
HTML:
<div id="slide-container">
<div id="slide">
SLIDE
</div>
</div>
CSS:
#slide-container
{
display: inline-block;
position: relative;
width: 66.666%;
}
#gallery-container:after
{
content: '';
display: block;
margin-top: 30.333%;
margin-top: -moz-calc( 33.333333% - 1.111111em ); /* because of some padding things */
margin-top: -webkit-calc( 33.333333% - 1.111111em ));
margin-top: calc( 33.333333% - 1.111111em );
}
#slide {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: silver /* show me! */
}
Though for the future I don't know why it didn't work …

Categories