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

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)'
});
}
});
});

Related

Issues with 'container' element on a horizontally draggable image gallery

I'm trying to make an image gallery that's navigated by dragging horizontally. The issue I'm currently facing is that there are no boundaries on the left and right for when the elements should stop dragging. I've tried using the 'container' element, but when I do, it stops dragging altogether.
I've tried using 'parent' or the actual div as the container and neither has worked properly. I saw on another message board that using flexbox in this situation makes things more complicated, so I switched to using display: inline-block on images.
This is my current draft: https://jsfiddle.net/samseurynck/ka1e9soj/21/
HTML
<div class="item_block_left">
<div class="item_block_left_gallery_container">
<div class="item_block_left_gallery">
<img class="item_block_left_gallery_item" src="https://placeimg.com/640/480/animals">
<img class="item_block_left_gallery_item" src="https://placeimg.com/200/200/animals">
<img class="item_block_left_gallery_item" src="https://placeimg.com/640/400/animals">
</div>
</div>
</div>
SCSS
.item_block_left{
height:200px;
width: 50%;
border: 1px solid pink;
overflow: hidden;
.item_block_left_gallery_container{
position: relative;
height:100%;
width: auto;
.item_block_left_gallery{
height:100%;
display: flex;
cursor: grab;
.item_block_left_gallery_item{
position: relative;
height:100%;
width:auto;
display: inline-block;
}
}
}
}
JQUERY
$(".item_block_left_gallery").draggable({
scroll: false,
axis: "x",
});
The intended result is only being able to scroll/drag horizontally as far as the images go, with no white space on the left or right sides.
Working Example: https://jsfiddle.net/Twisty/4ak6q0zu/44/
JavaScript
$(function() {
var bounds = {
left: $(".item_block_left_gallery").position().left
};
bounds.right = bounds.left - $(".item_block_left_gallery").width() - $(".item_block_left").width() + 10;
$(".item_block_left_gallery").draggable({
scroll: false,
axis: "x",
drag: function(e, ui) {
var l = ui.position.left;
if (l > bounds.left) {
console.log("Hit Left Boundry");
ui.position.left = bounds.left;
}
if (l <= bounds.right) {
console.log("Hit Right Boundry");
ui.position.left = bounds.right;
}
}
});
});
Using drag callback, you can check and set the position of the draggable item. Basing things off the left edge of the drag item, we can check and restrict the movement based on some specific boundaries. It appears that there was a 10px padding or margin on the right hand side, might just be white space, so I just adjusted to correct for this.
See more: http://api.jqueryui.com/draggable/#event-drag
Hope that helps.

scrolltop() triggering too early

I'm going crazy.. I'm trying to get the effect of sticky navigation, but instead of navigation, I have an image that should become fixed at the top of the page as soon as it hits the top of window, and then the following elements just scrolling on top of that image. That's my code:
The basic html is:
<section class="about">
...
</section>
<section>
<img src='' class="sticky">
<div> ...</div>
</section>
Javascript:
$(window).load(function() {
var sticky = $(".scroll");
var height = $("#about").height();
$(window).scroll(function() {
if($(this).scrollTop() > height ){
sticky.addClass("fix");
} else {
sticky.removeClass("fix");
}
});
})
It's working fine, except - the image (".sticky") becomes fixed too soon. I'm scrolling down, and even before my "about" section moves away, the image becomes fixed and jumps on top. The screenshot shows it. The big image with a girl on it has class "sticky"
here's the screenshot
Please help
You schould check img offset from top of the page and not the height of the <section class="about">.
I've used instead of an image, a div to show how 'sticky' should be achieved. You have also in your code snippet unclosed <section> tag.
var offset = $('.sticky').offset().top;
$(window).on('scroll', function () {
if ($(document).scrollTop() > offset) {
$('.sticky').addClass('fix');
} else {
$('.sticky').removeClass('fix');
}
});
.about {
height: 100vh;
width: 200px;
background: lightgreen;
}
.example {
background: lightblue;
height: 120vh;
width: 200px;
}
.sticky {
background: salmon;
width: 200px;
height: 100px;
}
.fix {
position: fixed;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="about"></section>
<section class="example">
<div class="sticky">quasi img</div>
<div> ...</div>
</section>

Adding a secondary element to show where user has dragged slider to in JQuery UI

Using the normal implementation of JQuery UI slider with this code:
$(function() {
$('.slider').slider();
});
JQuery UI only creates the surrounding slidable area, and then the handle to drag. Does anyone have experience extending this add an secondary element that shows where the user has dragged to? What I want to achieve is to have a two colour draggable area, either side of the handle.
You can add divs in the slider and update their size on slide event. Like this:
$('.slider').slider({
max: 100,
min: 0,
slide: function (e, ui) {
$('.left-side').css('width', $(ui.handle).position().left)
$('.right-side').css('width', $(e.target).width() - $(ui.handle).position().left)
}
});
$('.left-side').css('width', '0px');
$('.right-side').css('width', $('.slider').width())
.slider div {
position: relative;
height: 100%;
}
.left-side {
background-color: aliceblue;
left: 0px;
width: 200px;
float: left;
}
.right-side {
background-color: bisque;
width:200px;
float: left;
}
<link href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<div class='slider'>
<div class="left-side"></div>
<div class="right-side"></div>
</div>

Modal box "hidden" behind greyed out area

Im following along with http://multiplethreads.wordpress.com/tag/pagedown/
The example in the link above makes use of twitter bootstrap whereas i make use of zurb foundation.
Basically im trying to get a custom dialog box to insert images from my pagedown editior (sort of like how stackoverflow does it).
Im abale to pull up the modal box (foundation reveal) but it seems to be "behind" something and i cant seem to interact with it. Any ideas?
My code:
js file:
PH.ui.markdown = {
initialize: function () {
var markdownTextArea = $('textarea[data-markdown=true]');
if (markdownTextArea.length == 1) {
markdownTextArea.addClass('wmd-input')
.wrap("<div class='wmd-panel' />")
.before("<div id='wmd-button-bar'></div>")
.after("<div id='wmd-preview' class='wmd-preview'></div>");
var converter = Markdown.getSanitizingConverter();
var editor = new Markdown.Editor(converter);
editor.hooks.set("insertImageDialog", function (callback) {
//setTimeout(function () {
$('#myModal').foundation('reveal', 'open');
// }, 5000);
return true; // tell the editor that we'll take care of getting the image url
});
editor.run();
}
}
};
html:
<div id="myModal" class="reveal-modal">
<h2>Upload Image</h2>
<%= f.file_field :image %>
<button class="btn" id="insert_image_post">Insert Image</button>
<!-- <a class="close-reveal-modal">×</a> -->
</div>
I figured it out.
The wmd-prompt-background had a z-index of 1000:
<div class="wmd-prompt-background" style="position: absolute; top: 0px; z-index: 1000; opacity: 0.5; height: 1085px; left: 0px; width: 100%;"></div>
So i just added:
<style type="text/css">
#myModal {
z-index: 1500;
}
</style>
to my page and it worked.
One way to do it is to position the div of your modal directly under the <body>. This way you make sure that the modal is not part of elements with special z-index

jQuery Mobile - Slide In Alert Bar CSS over Header

I am trying to make an alert bar slide in over my header bar in jQuery mobile. So far I have got the slide in down, but I am having trouble with the CSS. I originally tried make the outer most div with position: absolute; top 0px: which makes it slide over the header from the top, but then inside Safari on the iPhone, the close button is cut off and you have to scroll to the right. How do I fix that?
Here is the HTML code for the alert bar:
<div class="ui-bar ui-bar-b error" style="position: absolute; top: 0px;">
<h3>
Form Validation Errors
</h3>
<div style="display:inline-block; width:8%; margin-top:0px; float: right;">
Dismiss
</div>
<ul class="validation_errors_list"></ul>
</div>
I ended up finally use this CSS. The alert bar slides directly over the header.
//you only really need this just to get it to slide over the header nicely and make sure you use top:0 if you always want it to be at the top. The plugin I made shows in/out the error message at position you are scrolled to in the document
.alert{
position: absolute;
z-index: 9998;
width: 100%;
height: 30px;
display: none;
color: #ffffff;
text-shadow: none;
font-family: Helvetica,Arial,sans-serif;
}
//This CSS is only used if you have an X button to close the alert. See the plugin below.
.alert-button-container{
display:inline-block;
margin-top:-10px;
margin-right: 15px;
float: right;
}
Here is my HTML Code (note the ui-bar class is a jQuery mobile class that you need to add so you don't have to mess around some of the width and sizing stuff).
<div class="ui-bar alert">
<div class="alert-message"></div>
</div>
Here is a custom plugin I made from jQuery to do this alert bar.
Features + Use Cases
Features: Fades In/Out gracefully, can inject custom HTML error messages, can render a list of messages, slides over header, has a close X button for error messages, works on all browsers that I have tested so far (IE, iOS, Firefox), error messages appear at the position you are scrolled to in the document. No more have to scroll up to see the error :)
Form Validation Errors. You can pass in an array of error messages and it will parse it into a list.
var messages = new Array();
messages[0] = 'My Message';
//prevent from showing accidentally
if(messages.length > 0)
{
$(".alert").alertBar('error', "<h2>Form Validation Errors</h2>", {
'errorMessages': messages
});
}
Success or action messages:
$(".alert").alertBar('success', 'Removed From Your Itinerary');
////////////plugin code
(
function($) {
$.fn.alertBar = function(alertType, alertMessage, userOptions) { //Add the function
var options = $.extend({}, $.fn.alertBar.defaultOptions, userOptions);
var $this = $(this);
$this.addClass(options.cssClass)
.empty()
.html(alertMessage)
.css('top', $(document).scrollTop());
if(alertType == 'success')
{
$this
.fadeIn()
.addClass('alert-success')
.delay(options.animationDelay)
.fadeOut();
}
if(alertType == 'error')
{
var button = $('<div>')
.addClass('alert-button-container')
.append(
$('<a>').attr({
'href': '#',
'data-role': 'button',
'data-icon': 'delete',
'data-iconpos': 'notext',
'class': 'dismiss-error'
})
.append('Dismiss')
);
//build error container
$this
.addClass('alert-error')
.append(button);
//add optional items to error container
if(options.errorMessages)
{
var $messageList = $('<ul>').addClass('error-message-list');
for ( var i=0, len=options.errorMessages.length; i<len; ++i ){
$messageList.append(
$('<li>')
.append(options.errorMessages[i])
);
}
$this.append($messageList);
}
//show alert bar
$this
.trigger('create')
.fadeIn();
$(".dismiss-error").live('click', function(){
$this.fadeOut();
});
}
if(alertType == 'informational')
{
$this
.addClass('alert-informational')
.fadeIn()
.delay(options.animationDelay)
.fadeOut();
}
return $this;
};
$.fn.alertBar.defaultOptions = {
cssClass : 'alert',
alertBarType: '',
animationDelay: 1500
};
})(jQuery);
additional CSS classes if you use this. It just changes the color of the bar.
.alert-success{
background-color: #8cc63f;
}
.alert-error{
background-color: #ed1c24;
height: auto;
}
.alert-informational{
background-color: #0071bc;
}
Example picture:

Resources