Anchor links not working with scroll snapping - anchor

I am using the following script to enable scroll snapping:
<style>
.scroll-snap-wrapper {
overflow: scroll;
scroll-snap-type: y mandatory;
scroll-behavior: smooth;
height: 100vh; /* Fallback for browsers that do not support Custom Properties */
height: calc(var(--vh, 1vh) * 100);
}
.section-waitlist-lp {
height: 100vh;
scroll-snap-align: start;
}
.section-waitlist-lp-last {
scroll-snap-align: end;
}
.scroll-snap-wrapper {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scroll-snap-wrapper::-webkit-scrollbar {
display: none;
}
</style>
Now an anchor link that I set on one of the buttons …
<a id="lp-button-2" href="#buttontarget" class="button-waitlist-lp-secondary w-button" style="display: block;">Find out more</a>
… doesn't work anymore, targeting the second section on the page
<div id="buttontarget" class="section-waitlist-lp wf-section">
I had a look at this question + answer on here based on this solution, but it didn't work for me. The staging site can be found here.
Any ideas? Thank you!

Related

position: fixed is not working in iOS when loading Angular site inside iframe in Ionic 3

Brief Description on what we are trying to achieve
We are developing an Angular application. We developed it for both Web and Mobile using same code base. Mobile version contains lot of features such as Push Notifications, SMS Subscriptions etc. We are hoping to publish mobile version to App store and Play store. We are using simple Ionic 3 app to build it to Android and iOS.
Ionic 3 application contains only one page in which we are loading our Angular Web Site inside an iframe.
HTML of Ionic page
<ion-content>
<iframe class= 'webPage' [src]="iframeSrc" webkitAllowFullScreen mozallowfullscreen allowFullScreen>
</iframe>
</ion-content>
TS of Ionic page
export class HomePage {
iframeSrc: any;
sanitizer: DomSanitizer;
url: string = 'https://angular-load-ionic-iframe.stackblitz.io';
constructor( sanitizer: DomSanitizer ) {
this.sanitizer = sanitizer;
this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
}
}
Find The Github Repository of Ionic 3 app Here.
I have created StackBlitz Angular project which similar to My Angular application. Find it Here.
My Issue
In my application, app-header and app-footer need to be fixed to
ViewPort and other content should be able to scroll. I successfully
achieved this for Android But in iOS, app-header and app-footer
are not fixed to ViewPort and those are scrolling with other content
when I load my Angular application inside an iframe in Ionic app.
header.component.html
<header>
<div class="main">
<h3>Countries</h3>
</div>
</header>
header.component.css
.main {
background-color: #46454A;
color: rgba(255,255,255,.6);
padding:5px 50px;
}
header{
position: fixed;
z-index: 10;
top: 0;
width: 100%;
}
footer.component.html
<footer class="footer">
<h3>This is footer</h3>
</footer>
footer.component.css
.footer{
position: fixed;
bottom: 0;
width: 100%;
background-color:#47454b;
}
h3 {
color: white;
padding:0px 50px;
}
I couldn't figure out Is it CSS issue with iOS or Is it occurred as I load angular web site inside iframe. Struggling for one day but still no success. If anyone can help me to fix this issue highly appreciated and If someone need more details about this feel free to comment.
put this css in your style.css
body {
margin: 0px;
}
h3 {
color: white;
padding:0px 50px;
}
my-app{
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
app-header,app-home,app-footer{
position: absolute;
left: 0;
width: 100%;
}
app-header,app-footer{
text-align: center;
color: white;
height: 50px;
background-color:#47454b;
}
app-header{
top:0;
}
app-footer{
bottom:0;
}
app-home {
top: 50px;
bottom: 50px;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
remove all css of header.component.css and footer.component.css
here is stackblitz link https://stackblitz.com/edit/angular-load-ionic-iframe-knkgq4?file=src%2Fstyles.css
Have you tried just setting the entire app mode / platform style to md via the app config? If you are able to solve this problem on Android then perhaps adopting Android styles globally for the iOS version will solve it for that platform too?
// app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { IonicModule } from '#ionic/angular';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { FooterComponent } from './footer/footer.component';
import { HomeComponent } from './home/home.component';
#NgModule({
imports: [
BrowserModule, FormsModule,
IonicModule.forRoot({
mode: 'md'
}),
],
declarations: [ AppComponent, HeaderComponent, FooterComponent, HomeComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Im not familiar with ionic and your angular setup but: there is a similar position fixed bug in safari Browsers.
The problem is: you cant position fixed Elements that are direct Children of the body tag.
The solution is: wrapping the content in another div. And putting every inside it.
Maybe you can try to put your Header and footer element inside an extra div so the footer isnt a direct child of the body tag.
Not tried, but worth a try:
style.css
body {
margin: 0px;
position: sticky;
z-index: -1;
width: 100%;
}
home.component.html
<div style="display: block;">
<div class="container" *ngFor="let country of countries">
<div class="code"><strong>Code:</strong> {{country.countryCode}}</div>
<div class="name"><strong>Name:</strong> {{country.countryName}}</div>
</div>
</div>
footer.component.css
.footer{
position: fixed;
bottom: 0;
width: 100%;
background-color:#47454b;
z-index:99;
}
h3 {
color: white;
padding:0px 50px;
}
I had similar issues in IE with sticky footer and header, this does the trick for me. You said that you are using iframes, but could not find some in your fork, only div-wrapped content... if you include the iframe, you can try to apply a relative positioning for the iframe like
position: relative;
to avoid collision with the header and footer. Hope this helps.

iOS Safari issue - Element becomes invisible while scrolling when changing position absolute to fixed

I want to use an element on the page as the title of the following content, but when the user is scrolling into the content this title-element should be fixed at the header. Similar to the ABC-captions in the iOS music-app.
See here: https://jsfiddle.net/1e7ync4w/
HTML
<div>
<div class="top">
Test
</div>
<div class="content">
<div class="scroller">
</div>
Test
</div>
</div>
CSS
.top {
background-color: yellow;
height: 300px;
}
.content {
position: relative;
height: 600px;
background-color: green;
}
.scroller {
position: absolute;
width: 100%;
height: 10px;
top: 0;
left: 0;
background-color: blue;
}
.scroller.fixed {
position: fixed;
}
JS
$(document).ready(function() {
$(window).on('scroll touchmove', function() {
$('.scroller').removeClass('fixed');
var scrollTop = $(window).scrollTop();
var scrollerOffsetTop = $('.scroller').offset().top;
if(scrollerOffsetTop <= scrollTop) {
$('.scroller').addClass('fixed');
}
});
});
The problem is that the iOS safari seems to have a bug with changing elements to fixed (via JavaScript) while scrolling. As soon as the user scrolls into the content, the title-element becomes invisible but shows after releasing the finger from the display (scroll-end).
I only tested this on the iOS 9.3.2 safari but I think this issue is older.
I found a solution for this problem. It's a little bit hacky but the only workaround I found for this iOS-bug.
The GPU of the browser needs to be "activated" for updating the according element. This can be achieved by setting a transform: translate-style via JS as soon as the positioning jumped to fixed.
The code of the example would look like this:
$(document).ready(function () {
$(window).on('scroll touchmove', function () {
$('.scroller').removeClass('fixed');
var scrollTop = $(window).scrollTop();
var scrollerOffsetTop = $('.scroller').offset().top;
if (scrollerOffsetTop <= scrollTop) {
$('.scroller').addClass('fixed').css({
'transform': 'translate3d(0px,0px,0px)',
'-moz-transform': 'translate3d(0px,0px,0px)',
'-ms-transform': 'translate3d(0px,0px,0px)',
'-o-transform': 'translate3d(0px,0px,0px)',
'-webkit-transform': 'translate3d(0px,0px,0px)'
});
}
});
});

Highlight Nav item when using anchor scrolling

I'm pretty new when it comes to jQuery so I need someone with a little more experience to help me out. I have a Nav with 3 items - Work About Contact
By default I have work selected but I would like it to change the active class to which ever is clicked. I have anchor scrolling working but I would like to have it highlight to the correct nav item when clicked. Also if it is possible when scrolling down the page and getting to the next section for it to change highlight automatically.
This is the jQuery I am using for the anchor scrolling.
<script>$(function() {
var main-nav = $("#main-nav"), pos = main-nav.offset();
$(window).scroll(function() {
if($(this).scrollTop() > (pos.top + 10) && $(this).scrollTop() < 15000 && main-nav.css('position') == 'static') { main-nav.addClass('fixed'); }
else if($(this).scrollTop() <= pos.top && main-nav.hasClass('fixed')){ main-nav.removeClass('fixed'); }
else if($(this).scrollTop() > 15000 && main-nav.hasClass('fixed')){ main-nav.removeClass('fixed'); }
})
});
</script>
<script>$(function() {
$('ul.nav a').bind('click',function(event){
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 1500,'easeInOutExpo');
/*
if you don't want to use the easing effects:
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 1000);
*/
event.preventDefault();
});
});
</script>
Here is the CSS
#main-nav{
font: bold 12px 'Bitter', serif;
width: 145px;
float: right;
}
#main-nav li{
float: left;
list-style: none;
margin: 10px 2px 0 2px;
color: #c4c5c5;
}
#main-nav li:last-child{
margin-right: 0;
}
#main-nav a{
text-decoration: none;
color: #c4c5c5;
}
#main-nav a:hover{
text-decoration: none;
color: #919292;
}
#main-nav a.active{
color: #919292;
}
Here is the HTML
<div id="main-nav" class="">
<ul class="nav">
<li><a class="active" href="#work">Work</a></li>
<li>/</li>
<li>About</li>
<li>/</li>
<li>Contact</li>
</ul>
</div>
If someone could help me out I would really really appreciate it!
Since you are using the active class to specify which anchor should be highlighted, you just need to make sure that the correct anchor has that class. Fixing that when the nav items are clicked is straightforward, in your $('ul.nav a').bind add:
$('ul.nav a').removeClass('active');
$(this).addClass('active');
Here is a jsbin.
To highlight the nav's as the page is scrolled you would just compare the scrollTop for the page with the offsets of elements in the DOM...similar to your current code in $(window).scroll.

How can I make the YouTube player scale to the width of the page but also keep the aspect ratio?

I have a YouTube video I want to put on my web page.
I want to scale the video to fit to a percent of the users browser but also to keep the aspect ratio.
I have tried this:
<iframe width="87%" height="315" src="http://www.youtube-nocookie.com/embed/dU6OLsnmz7o" frameborder="0" allowfullscreen></iframe>
But that does only make the player wider, not higher.
Does I have to resort to JavaScript (or non-standard CSS)?
What i believe to be the best CSS solution.
.auto-resizable-iframe {
max-width: 420px;
margin: 0px auto;
}
.auto-resizable-iframe > div {
position: relative;
padding-bottom: 75%;
height: 0px;
}
.auto-resizable-iframe iframe {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
<div class="auto-resizable-iframe">
<div>
<iframe frameborder="0" allowfullscreen="" src="http://www.youtube.com/embed/_OBlgSz8sSM"></iframe>
</div>
</div>
Demo http://jsfiddle.net/46vp592y/
I hit a similar issue with my site when developing some responsive CSS. I wanted any embedded Youtube objects to resize, with aspect, when switching from the desktop CSS to something smaller (I use media queries to re-render content for mobile devices).
The solution I settled on was CSS and mark-up based. Basically, I have three video classes in my CSS thus:
.video640 {width: 640px; height: 385px}
.video560 {width: 560px; height: 340px}
.video480 {width: 480px; height: 385px}
… and I assign one of these to the Youtube content I include, depending on its original size (you may need more classes, I just picked the most common sizes).
In the media query CSS for smaller devices, these same classes are simply re-stated like so:
.video640 {width: 230px; height: 197px}
.video560 {width: 230px; height: 170px}
.video480 {width: 240px; height: 193px}
I appreciate this requires some mark-up "up-front" when including videos in your HTML (i.e. adding a class), but if you don't want to go down the Javascript route, this works pretty well -- you could re-state your video classes for as many different sizes as you require. Here's how the Youtube mark-up looks:
<object class="video640" type="application/x-shockwave-flash" value="YOUTUBE URL">
<param name="movie" value="YOUTUBE URL"></param>
</object>
Quite easy with some javascript.
jQuery(function() {
function setAspectRatio() {
jQuery('iframe').each(function() {
jQuery(this).css('height', jQuery(this).width() * 9/16);
});
}
setAspectRatio();
jQuery(window).resize(setAspectRatio);
});
This jQuery plugin has been making the rounds of late, it's called FitVids and does exactly what you need, resizes videos based on browser size whilst maintaining aspect ratio.
http://fitvidsjs.com/
Modern Solution (2022) - aspect-ratio
With the introduction of the aspect-ratio property in CSS, it's now very simple to scale a YouTube video without resorting to CSS hacks or JS.
Example:
iframe {
aspect-ratio: 16 / 9;
height: auto;
width: 100%;
}
The aspect-ratio property is widely supported across browsers making it suitable for the vast majority of sites: https://caniuse.com/mdn-css_properties_aspect-ratio
These work a treat no JS. Responsive for both single palyer and list player modified from somewhere not sure, no credit sorry. Load your iframe Youtube player inside a container div, the iframe style sets the player specific sizing, 100% will fill the container to any size, src= your-youtube-ID, add own player options
https://jsfiddle.net/jcb01/04sf3byz/
<div style=" position: relative; padding-bottom: 56.25%;">
<!--- load iframe Youtube player inside this div -->
<iframe
style="border: 1; top: 0; left: 0; width: 100%; height: 100%; position: absolute;"
src="https://www.youtube-nocookie.com/embed/?
list=PL590L5WQmH8fmto8QIHxA9oU7PLVa3ntk;
&autoplay=0&enablejsapi=1&index=0&
listType=playlist&loop=1&modestbranding=1"
allowfullscreen scrolling="no"
allow="encrypted-media; accelerometer;
gyroscope; picture-in-picture">
</iframe>
</div>
The trick to make a youtube video autoresize is to make the iframe width 100% and put it in a div with a "padding-bottom" equal to the aspect ratio in percentage. E.g.
But the problem is - you would have a lot of pages with embedded YoutTube videos already. Here's a jquery plugin that will scan all videos on the page and make them resizable automatically by changing the iframe code to be as above. That means you don't have to change any code. Include the javascript and all your YouTube videos become autoresizing.
https://skipser.googlecode.com/files/youtube-autoresizer.js
Old question, but I think the #media CSS 3 tags would be helpful in this instance.
Here is my solution to a similar problem.
The CSS:
#media only screen and (min-width: 769px) {
.yVid {
width: 640px;
height: 360px;
margin: 0 auto;
}
}
#media only screen and (max-width: 768px) {
.yVid {
width: 560px;
height: 315px;
margin: 0 auto;
}
}
The HTML:
<div class="yVid">
<iframe width="100%" height="100%" frameborder="0" allowfullscreen="" src="http://www.youtube.com/embed/_OBlgSz8sSM"></iframe>
</div>
This basically adds a breakpoint at 768px where the video resizes itself. You could also add breakpoints at 992 and 1280 for an even more repsonsive video size. (numbers based on Bootstrap standard sizes).
This is what worked for me. This is slightly modified code from the YouTube Embed Code Generator.
The CSS:
.video-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.27198%;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
The HTML:
<div class="video-container">
<iframe width="560px" height="315px" src="https://www.youtube.com/embed/XXXXxxxx?&theme=dark&autohide=2&iv_load_policy=3"><iframe>
</div>
You can use style="max-width: %87; max-height: %87;"
In addition to Darwin and Todd the following solution will
avoid the bottom margin
maximize the width for large screens
minimize the height in mobile view
keep a fixed size for #media none compatible browsers
The HTML:
<div class="video_player">
<div class="auto-resizable-iframe">
<div>
<iframe frameborder="0" allowfullscreen="" src="http://www.youtube.com/embed/_OBlgSz8sSM"> </iframe>
</div>
</div>
</div>
The CSS:
.videoplayer{
text-align: center;
vertical-align: middle;
background-color:#000000;
margin: 0;
padding: 0;
width: 100%;
height:420px;
overflow:hidden;
top: 0;
bottom: 0;
}
.auto-resizable-iframe {
width:100%;
max-width:100%;
margin: 0px auto;
}
.auto-resizable-iframe > div {
position: relative;
padding-bottom:420px;
height: 0px;
}
.auto-resizable-iframe iframe {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
//full screen
#media (min-width:0px) {
.videoplayer{
height:100%;
}
.auto-resizable-iframe > div {
padding-bottom:100%;
}
}
//mobile/pad view
#media (min-width:600px) {
.videoplayer{
height:420px;
}
.auto-resizable-iframe > div {
padding-bottom:420px;
}
}
There are a few suggestions on the list of answers to use js to modify the structure of generated iframe. I think there is a risk with that because when you wrap the iframe inside other elements it's possible that the YouTube API will lose 'connection' with the iframe (especially if you pass the element in as a node instead of using specific id like me). It's rather to get around it actually, use javascript to modify the content before you actually trigger the youtube player.
a snippet from my code:
/**
* Given the player container, we will generate a new structure like this
*
* <div class="this-is-the-container">
* <div class="video-player">
* <div class="auto-resizable-iframe">
* <div>
* <iframe frameborder="0" allowfullscreen="" src="http://www.youtube.com/embed/_OBlgSz8sSM"> </iframe>
* </div>
* </div>
* </div>
* </div>
*
* #return {Node} the real player node deep inside
*/
YouTube.renderResizable = function (playerContainer) {
// clean up the content of player container
playerContainer.textContent = '';
var playerDiv = document.createElement('div');
playerDiv.setAttribute('class', 'video-player');
playerContainer.appendChild(playerDiv);
// add the auto-resizable-frame-div
var resizeableDiv = document.createElement('div');
resizeableDiv.setAttribute('class', 'auto-resizable-iframe');
playerDiv.appendChild(resizeableDiv);
// create the empty div
var div = document.createElement('div');
resizeableDiv.appendChild(div);
// create the real player
var player = document.createElement('div');
div.appendChild(player);
return player;
};
Just set iframe height and width with CSS vw metric. It uses device width as parameter:
.videoWrapper iframe {
height: 36.6vw;
width: 65vw;
}
You could use two classes that would scale the size of the video based on the size of the wrapping div. Consider this example:
<div class="content-wrapper">
<div class="iframe-wrapper res-16by9">
<iframe src="https://www.youtube.com/embed/pHsYFURtzzY" frameborder="0" allowfullscreen></iframe>
</div>
</div>
Now look at the css.
.content-wrapper{
max-width: 800px;
margin: 0 auto;
background-color: #fff;
}
.iframe-wrapper{
width: 100%;
position: relative;
}
.res-4by3{
padding-bottom: 75%;
}
.res-16by9{
padding-bottom: 56.25%;
}
.iframe-wrapper iframe{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Note that you will have to wrap the iframe in a div who's width is set to 100% and position is set to relative. You have to also add a bottom-padding to iframe wrapper. This padding will define the height of a video. I recommend to create two classes that will represent the image ratio.
It is quite easy to calculate the right bottom-padding for wrappers that represent certain resolution. For example for res 4 by 3 and 16 by 9 would have bottom-padding equal to:
[4/3 res]
100 / 4 * 3 = 75%;
[16/9 res]
100 / 16 * 9 = 56.25%
Then position the iframe as absolute and push it to the top left corner of the wraping div. Also meke sure to set iframe width and height to 100%. You are done.
Add the class that fits the right resolution for you. It will scale the image width and height respectively keeping the right proportions in place.
The example above works for any iframe. Thats mean you can also use it for google maps iframe.
Add JavaScript code to give each youtube iFrame a class:
$('iframe[src*="youtube"]').addClass('youtube')
Then in the Media Queries use the you tube class to set a different size.
.youtube {
/* Do stuff here */
}
Easier and optimized to CMS than the manual way.

sIFR 3 - I can't get it to display anything

I'm trying to implement the latest sIFR. But I can't get even the simplest of tests to work. My test page is at http://www.kellymitchelljewelry.com/testsifr.asp. There should be an sIFR-generated line that says "2nd line" between the first and third lines. I'm using the examples provided on the sIFR page exactly.
My html looks like this:
<html>
<head>
<title>Kelly Mitchell Fine Jewelry</title>
<link rel="stylesheet" href="sifr.css" type="text/css">
<script src="sifr.js" type="text/javascript"></script>
<script src="sifr-config.js" type="text/javascript"></script>
</head>
<body>
First Line<br><br>
<h1>Second Line</h1>
<br>Third Line<br><br>
</body>
</html>
My sifr-config.js looks like this:
var cgoth = { src: 'cgoth.swf' };
sIFR.activate(cgoth);
sIFR.replace(cgoth, {
selector: 'h1'
});
My sifr.css file looks like this:
#media screen {
.sIFR-flash {
visibility: visible !important;
margin: 0;
padding: 0;
}
.sIFR-replaced, .sIFR-ignore {
visibility: visible !important;
}
.sIFR-alternate {
position: absolute;
left: 0;
top: 0;
width: 0;
height: 0;
display: block;
overflow: hidden;
}
.sIFR-replaced div.sIFR-fixfocus {
margin: 0pt;
padding: 0pt;
overflow: auto;
letter-spacing: 0px;
float: none;
}
}
#media print {
.sIFR-flash {
display : none !important;
height : 0;
width : 0;
position : absolute;
overflow : hidden;
}
.sIFR-alternate {
visibility : visible !important;
display : block !important;
position : static !important;
left : auto !important;
top : auto !important;
width : auto !important;
height : auto !important;
}
}
/*
Place CSS rules for to-be-replaced elements here. Prefix by .sIFR-active
so they only apply if sIFR is active. Make sure to limit the CSS to the screen
media type, in order not to have the printed text come out weird.
*/
#media screen {
.sIFR-active h1 {
font-family: Verdana;
visibility: hidden;
line-height: 1em;
}
*/
I've tried recreating my swf file just in case I did something wrong, and closely followed the instructions to make sure I didn't leave anything out.
Can someone help me figure what I'm doing wrong?
Tom
I don't think your Flash movie is correct, opening it directly should show "Rendered with sIFR 3" text. Make sure it was exported correctly.
I have never been able to get a .swf file exported from Flash to work with sIFR. I've always ended up having to use the online sIFR generator: http://www.sifrgenerator.com/wizard.html
I don't know if my version of Flash (CS3) is just not compatible with sIFR or what... I do always save as version 8 like it says to, and make sure every setting is as it should be, but no luck. However, using that generator always seems to solve it. So if your Flash is jinxed to, you might want to give it a try.

Resources