Background image blurry when scaling on iPad and iPhone - html

I'm creating a web app where I allow users to zoom certain 100x100px background images.
When they double tap the image, I scale the image to twice its size (-webkit-transform: scale( 2 )).
When the transition is done, I swap the 100x100px image with a larger 200x200px image. For some reason, the image is very blurry.
So I tried to use an img tag instead of a div tag to show my images. Here the image isn't blurry at all. Why is this?
I NEED to use background images to circumvent the memory limit on the iPad and iPhone (if I use img tags I will hit a memory wall).
Can anyone help me? Thank you so much.

Im claiming 3 things:
Scaling a div stretches the pixels and not adding more.
background-size: contain; Ensures you that your background-image is fully showen
The div never change size.
As you can see here the div is still 200x200 pixels
The image is resized to be 200x200 pixels Even if it's 400x400 pixels. See here
Almost proved in 1. the font is still sharp but javascript thinks the width and height is 200x200 pixels.
Okay so for your fix:
There are several ways.
You can change width and height instead of scaling. This isn't any pretty, or at least you are very lucky if this animation doesn't lack it's way throw (on iOS).
Something else could be scaling and detection webkitTranstionEnd
$('div').bind("webkitTransitionEnd", function() {
$(this).css({
"-webkit-transform": "scale(1)",
"width": "400px",
"height": "400px"
});
$(this).unbind("webkitTransitionEnd");
});
Remember to unbind the webkitTransitionEnd event. Else its doubling the function call.
But what happend it's animation back. So we have to keep the transtion in a class so we can add and remove it when we want:
div {
-moz-transition-duration: 0ms;
}
div.transition {
-moz-transition-duration: 200ms;
}
And then add the class when we have to animate:
setTimeout(function() {
$('div').addClass("transition");
$('div').css({
backgroundImage: 'url(http://img812.imageshack.us/img812/212/cssc.png)',
webkitTransform: 'scale( 2 )',
mozTransform: 'scale( 2 )'
});
}, 3000);
And remove it again in webkitTransitionEnd
$(this).removeClass('transition');
$(this).css({
"-webkit-transform": "scale(1)",
"width": "400px",
"height": "400px"
});
$(this).unbind("webkitTransitionEnd");
What??! It dosn't add / remove the class in time?! What happen.
Sometimes the browser needs a little while to make sure the class is added. Therefore you need to wrap the setting of css in a setTimeout(function(){...}, 0);
setTimeout(function() {
$('div').addClass("transition");
setTimeout(function(){
$('div').css({
backgroundImage: 'url(http://img812.imageshack.us/img812/212/cssc.png)',
webkitTransform: 'scale( 2 )',
mozTransform: 'scale( 2 )'
});
}, 0);
}, 3000);
Also when we remove the class:
$(this).removeClass('transition');
setTimeout(function(){
$(this).css({
"-webkit-transform": "scale(1)",
"width": "400px",
"height": "400px"
});
$(this).unbind("webkitTransitionEnd");
}, 0);
So long, now the problem is that it's scaling up and get blurred and after the scale it gets super sharp.
What we can do about it I dont know, but hope it helps you some where!
Andreas

Related

How to fix zoom issues with Google Chrome and 1px Width/Height DIVs?

Goal: Draw a fixed grid on the screen to use with jQuery's draggable snap option as part of a form designer. Allow user to zoom in and out while still maintaining the 25x25 px grid.
Problem: The grid is drawn with a 1px width DIV for vertical lines and a 1px height DIV for horizontal lines. At normal zoom in Chrome the DIVs display fine, however, at varying zoom levels some of the DIVs will not display at all. The problem was noted with 90% zoom and 75% zoom but also occurred in others. If zooming in past 100% it seems fine. I couldn't re-produce the problem in IE or MS Edge.
What I know: I looked around for a while for a solution. Based on that research and inspecting the computed styling I believe the problem is that Chrome is calculating a new width/height when zoomed and if the calculation result is less than 1 it will not display as 1px is the smallest unit the browser will display. I toyed around with adding a border but that seems to throw off my positioning.
Here is my javaScript:
$(document).ready(function(){
var i,
sel = $('#myDIV'),
size = 25,
height = sel.height(),
width = sel.width(),
ratioW = Math.floor(width / size),
ratioH = Math.floor(height / size);
for (i = 0; i <= ratioW; i++) { // vertical grid lines
$('<div />').css({
'top': 0,
'left': i * size,
'width': 1,
'height': height
})
.addClass('gridlines')
.appendTo(sel);
}
for (i = 0; i <= ratioH; i++) { // horizontal grid lines
$('<div />').css({
'top': i * size,
'left': 0,
'width': width,
'height': 1
})
.addClass('gridlines')
.appendTo(sel);
}
$('.gridlines').show();
})
Here is my CSS:
.gridlines {
display: none;
position:absolute;
background-color:#ccc;
opacity: 0.6;
filter: alpha(opacity=60); /* For IE8 and earlier */
}
And finally a jsFiddle to demonstrate the issue. In my actual scenario I can see the problem at 90% zoom but in the jsFiddle I don't see the problem until 75% zoom.
https://jsfiddle.net/r5xjsf6f/
UPDATE:
So based on a comment suggesting that I detect the zoom and modify the css accordingly I started digging into that. I found that I could analyze the computed style and if it was less than 1px I could increase the inline style to 2px and then it would show. I don't really like this but I wanted to try something. The odd thing is in testing I found that at some zoom levels the computed style was 1px and they still didn't show. Any ideas on that part of it or a better solution?
Here is the code I added:
if(!!window.chrome){
$(".ghorizontal").each(function(){
if($(this).height()<1){
$(this).css("height","2px");
}
})
$(".gvertical").each(function(){
if($(this).width()<1){
$(this).css("width","2px");
}
})
}
Here is an updated jsFiddle:
https://jsfiddle.net/r5xjsf6f/1/
UPDATE:
Since I wasn't able to find a solution for this we ended up just changing our grid lines width/height to 2px instead of 1px. This seems to allow the lines to display correctly until about 33% zoom level. Before it was breaking at more realistic zoom levels. This isn't a full solution but is more in the realm of reasonability for our application. I welcome better solutions if they are out there but we are gonna roll into production with this for now.
I am actually trying to accomplish something similar with the same code and I ran into the same exact problem. I managed to fix the issue by setting the width and height to zero and putting a border-left on the vertical lines and a border bottom on the horizontal lines like so:
$('<div />').css({
'top': 0,
'left': i * size,
'width': 0,
'border-left': '1px solid #ccc',
'height': height
})
.addClass('gridlines')
.appendTo(sel);
}
for (i = 0; i <= ratioH; i++) { // horizontal grid lines
$('<div />').css({
'top': i * size,
'left': 0,
'width': width,
'border-top': '1px solid #ccc',
'height': 0
})
.addClass('gridlines')
.appendTo(sel);
}
Here is an updated version of your fiddle

How to set div to expand with transition on text change

I want to seamlessly expand my div (in a non-jarring way) when the text inside it changes:
The CSS transition: all 2s ease; is working great for colour changes, manually setting width, etc (as you can try out in the jsfiddle - click button to toggle width). but when the inner text of the div is changed the div just jumps to the new width without any transition.
How can I get the transition working when the inner text changes?
Thanks!
Because the default width of the div will be auto (100%), it can't transition from auto to a numerical value.
I don't think dynamically changing a width of an element depending on its content is possible, as there is no transition for content. The content of an element changes instantly and the width does not get a numerical value in your case - but adjusts.
A solution that can be sometimes applicable: Using a function to roughly calculate your text's width so that you'll be able to set a numerical width for your element on change.
Here's a simple one that I made.
function getTextWidth(text, css) {
var e = $('<span></span>'); // dummy element
e.css(css); // set properties
e.text(text); // set test
var width = e.appendTo($('body')).width(); // append and get width
e.remove(); // remove from DOM
return width;
}
Put together an example of usage.
Hi abagshaw try this script to solved your problem.
var big = false;
$('#content').on('click', function(e) {
if(!big)
{
$( this).animate({
width: "600px" }, 500 );
this.innerHTML = "MORETEXTMORETEXTMORETEXTMORETEXTMORETEXTMORETEXTMORETEXT";
big = true;
}
else
{
$( this).animate({
width: "200px" }, 500 );
this.innerHTML = "LESSTEXTLESSTEXT";
big = false;
}
});
.ui.transitioning.button{
transition:all 0.5s ease-in-out;-webkit-transition:all 0.5s ease-in-out;
width:200px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.0.7/semantic.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ui transitioning teal button" id="content">LESSTEXTLESSTEXT</div>

Scroll to top when overflow is hidden

Is there a way to scroll the content of an element that has an overflow of hidden to the top?
Example use case:
Container element has a max height of 200px, starting position is at 60px.
User clicks "show more", the height expands to 200px.
Since there is more content than 200px allows, the user can scroll to the bottom of the list.
When the user clicks "show less", the height lowers to 60px.
Problem arises, in that the list is no longer at the top and not scrollable.
Any ideas here would be great.
I believe it is not possible with CSS.
You can try to look at element.scrollIntoView.
Searching for scrollIntoView I found this question on SO where the answer suggests using jQuery's scrollTop.
Do you mean something like that?
http://jsfiddle.net/8pvjf/
It has to do with jquery indeed
$(document).ready(function(){
$('.background').css('font-size',($(window).width()*0.1));
$(".blow").each(function(){
});
$('.blow').on('click', function(event){
var element = $(this);
if(element.attr('data-blow') == 'true'){
element.animate({ width:'24%', height:'20%' , opacity:0.6 }, 1000).attr('data-blow', 'false')
$(this).addClass('blow')
$(this).removeClass('overflow')
} else {
element.animate({ width:'100%', height:'100%' , opacity:0.95 }, 1000, function(){
$('body').animate({ scrollTop: element.offset().top });
}).attr('data-blow', 'true').addClass('overflow').removeClass('blow');
}
});
$(window).resize(function(){
$('.background').css('font-size',($(window).width()*0.1));
});
Have fun toying with those codes as much as you want.
Of course, this is based on some previous work of mine and you'll need to change your classes and styles accordingly to your needs. :)

Scroll background image untill the end not further

I am working on a site and I don't want to repeat the background in the y direction.
I know how to do that.
But after the image I don't want background to becomes white or any other color.
I would like it to fix when it reaches that place or to let the background scroll slower then the rest of the site so I wont get to a white part.
Thanks a lot
I found this thread while I was looking for a solution to just this problem. I managed to write a short jQuery script adapting the hints given by Alex Morales.
With the following code, the background-image of the body scrolles down with the rest of the site until its bottom is reached. You can take a look at my homepage (http://blog.neonfoto.de) to see what it does.
$( window ).scroll( function(){
var ypos = $( window ).scrollTop(); //pixels the site is scrolled down
var visible = $( window ).height(); //visible pixels
const img_height = 1080; //replace with height of your image
var max_scroll = img_height - visible; //number of pixels of the image not visible at bottom
//change position of background-image as long as there is something not visible at the bottom
if ( max_scroll > ypos) {
$('body').css('background-position', "center -" + ypos + "px");
} else {
$('body').css('background-position', "center -" + max_scroll + "px");
}
});
This is actually the very first thing I did with JavaScript and JQuery, so any improvement would be great!
It's css3 so it's not super well supported, but I would look at the background-size property.
This is just off the top of my head but I think you will probably have to create a separate div containing the background image. If you place it in your markup before the main content and position the main content absolutely, it will sit behind the main content and at the top of the page. So:
CSS:
#background_div
{
background: url(images/some_image.png);
height: 600px;
width: 900px;
}
#main
{
height: 1200px;
width: 800px;
background: rgba(0, 0, 0, 0.25);
position: absolute;
top: 0;
}
HTML:
<div id="background_div"> </div>
Then what you do is you use javascript (I recommend jQuery) to detect the div's position on the screen.
jQuery:
This code grabbed from http://www.wduffy.co.uk/blog/keep-element-in-view-while-scrolling-using-jquery/
var $scrollingDiv = $("#background_div");
$(window).scroll(function(){
$scrollingDiv
.stop()
.animate({"marginTop": ($(window).scrollTop()) + "px"}, "slow" );
});

Zoom ignoring pictures

I would like to take the contents of an HTML page, an make every element 50% larger. I have tried using CSS3 zoom: 150% but this also attempts to zoom pictures. Because the resolution of the images were originally crafted for a normal view, they look blurry with the zoom.
Is it possible to make all HTML bigger, except for the images?
When you apply a scale transformation to an element, the magnification is applied to the element itself and to all of their children. This is a behavior common to most browsers, with the exception of IE (I believe).
So, to do what you want, you need to scale only the following elements:
elements that are not img and do not contain any img descendants
By using jQuery
$("button").click(function () {
$("*").each(function (index, value) {
var $this = $(value);
// if this is not an image
if (!$this.is("img") &&
// and if it does not contain child images
$this.find("img").length == 0) {
// then scale it up
$this.css({
'-webkit-transform': 'scale(1.5)',
'-moz-transform': 'scale(1.5)',
'-o-transform': 'scale(1.5)',
'-ms-transform': 'scale(1.5)',
'transform': 'scale(1.5)'
});
}
});
});
You can see it live here
you can also use
$this.css('zoom', '1.5');
instead of
$this.css({
'-webkit-transform': 'scale(1.5)',
'-moz-transform': 'scale(1.5)',
'-o-transform': 'scale(1.5)',
'-ms-transform': 'scale(1.5)',
'transform': 'scale(1.5)'
});
try transform: scale(1.5); This should help
A crude way of doing it would be to have:
body {
zoom: 150%;
}
img {
zoom: 67%
}
That will not rescale background images or other non-img elements, so it's not ideal.