How to stop Safari on iOS highlight the whole image? - css

In order to have responsive images on a web-site, I am using overflow: hidden style on the image's container, with other rules related to max-height and automatic width so for the given screen width images have the same ratio on the visible area, almost no matter what is the image itself. And it works with landscape images well.
However, some portrait-oriented images have long hidden area, and when you tap the link on the image in iPhone's Safari, it will show (highlight) the whole extent of the image in addition to Save and other options' menu.
Markup used is roughly this:
<figure>
<div class="image-wrapper">
<a href="...">
<img src="http://lorempixel.com/200/400/">
</a>
</div>
</figure>
Styles (excerpt, without widths and unrelated):
a {
max-width: 900px;
max-height: 120px;
overflow: hidden;
display: block;
}
div {
max-width: 900px;
position: relative;
overflow: hidden;
max-height: 120px;
}
img {
width: 100%;
}
At first I thought, that it is because <a> fills <img>, so I've added display: block and max-height, but it does not help. This means, that tap menu is for the image, and full image is hightlighted.
Is there any way to show only visible part in tap highlight?

One option is to give pointer-events: none declaration the image element.
It prevents the image from being the target of the pointer (on click/tap).
For instance:
a img { pointer-events: none; }
It's worth noting that pointer-events is supported in iOS Safari 3.2+.

Related

Wrapping a link around an image destroys flexbox layout and causes browser rendering quirks

Struggling to find the right title that isn't just a mixture of "help" and "what, CSS, why?!" so hopefully a couple of you geniuses will find this...!
I have two columns. Each of them has a full-width div inside it which contains a logo. The images are quite different shapes, one being a square and one being a more panoramic aspect ratio. To achieve a balanced look, the images are set to a max-width of 50% and a max-height of 100%. Flexbox is used to center the images both horizontally and vertically.
They look perfectly fine.
// working before wrapping images with links
section.working {
div.flex {
display: flex;
justify-content: center;
align-items: center;
img {
max-width: 50%;
max-height: 100%;
}
}
}
And then I needed to add links.
https://codepen.io/lenoz/pen/VwZyeOG
This is the problem reduced to its most simple, in that the bottom row was the original code I was using to get the perfect layout, and the top row shows what happens when the images were wrapped in tags to make them links. Some points of note:
colours added just to help distinguish boundaries a little - useful for detecting when the link (red background) is no longer constricted to the size of the image inside it (as it ideally should be)
the two columns are separate in the code and not part of a shared container - i.e. one cannot inform the height of the other (want to fix this with CSS not JS)
I should mention that of course there was no way adding links would just work - the <a> tags come in between the flex container and the flex item, so obviously they will mess with the layout.
Much appreciated if you can help me find a CSS solution.
Still here? Read on if you want some more info on my attempts to fix, with a side portion of Chrome weirdness.
It should also go without saying I've spent ages fiddling with this, so here's another link showing some of my efforts that have gotten close: https://codepen.io/lenoz/pen/pozpjVq
The top row (section.help) is my latest attempt, but is a bit of a mess simply because I stopped half way, having suffered frustration sufficient to lead to me making this post.
The middle row, which I'm calling section.weirdness, actually seemed to be a solution for a hot minute. If you're using Chrome, like I am, when you look at the Codepen link you may see nothing on these blue blocks?
But try removing the display: flex attribute from div.flex and, if your Chrome is like my Chrome, you'll see this:
Now, add that same display: flex attribute back on the same div.flex selector and you'll see that suddenly the blue blocks are not blank:
How strange is that? Browser rendering bug or what?
Now find the max-width or max-height attributes on div.image, toggle one of those off and then on again and you'll see that everything suddenly looks right again:
Somehow, without changing any CSS other than toggling it, we've gone from no links showing up at all, to them showing up and looking perfect. You can see how I'd managed to confuse myself into thinking I had got it working!
Just add style="display: contents" to your anchors
"display: contents" causes an element's children to appear as if they were direct children of the element's parent, ignoring the element itself
<div>
<a style="display: contents" href="#">
<img src="https://via.placeholder.com/1000x300.png" />
</a>
</div>
Here's a simple solution:
I've changed the columns to be flex contexts but retained an inner div to serve as the 50% width constraint. When the imgs are allowed to set their own height explicitly all the other constraints around them flow into place without much fuss, and because the anchors don't have any layout rules, they manage to avoid having any clickable areas outside their image.
With the same max-height on the images, they'll match in the same way as your .working class as long as their containers are the same width.
section {
width: 800px;
display: flex;
}
.column {
background-color: blue;
margin: 5px;
width: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.column > div {
max-width: 50%;
}
img {
display: block; /* get rid of bottom gap */
max-width: 100%;
max-height: 80px;
}
<section>
<div class="column">
<div>
<a href="#">
<img src="https://via.placeholder.com/500x500.png" />
</a>
</div>
</div>
<div class="column">
<div>
<a href="#">
<img src="https://via.placeholder.com/1000x300.png" />
</a>
</div>
</div>
</section>
Try adding this to your Codepen example:
.flex > a {
flex: 0 0 50%;
height: 100%;
display: flex;
}
div.flex a > img {
max-width: 100% !important;
max-height: 100% !important;
margin: auto;
}
Any immediate child of a container with display: flex is flex item. To prevent that item from growing or shrinking we must set flex-grow and flex-shrink properties to 0. In my case I used flex: 0 0 50% shorthand for that. That last value of 50% is from your initial image max-width property. That + height:100% will make sure that <a> behaves like images in your original example.
Now the fun part: use display: flex again on <a> to make the image flex item again. Since <a> is already properly sized we can set max-width and max-height to `00% to fill available space.
Using margin: auto is a neat trick to center both horizontally and vertically flex child inside of flex container (works only when there is one child).
sidenote: I used important to override specificity without changing markup but I would advise against it and put new CSS class on both a and img.
UPDATE
working fork (Chrome only): https://codepen.io/teodragovic/pen/wvwpWbx?editors=1100
section.broken {
.flex {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
a {
max-width: 50%;
max-height: 100%;
}
img {
max-width: 100%;
max-height: 100%;
display: block;
}
}

Image as a flex item not scaling with max-width in Chrome

I have an image within a flex container.
The image stays at its original height in Chrome and will not resize proportionally. It works in Firefox however.
<figure>
<img src="image.jpg">
A link to somewhere
</figure>
figure {
display: flex;
width: 100%;
}
figure img {
max-width: 50%;
height: auto;
}
Flex makes its children equal in height by default. To disable this behavior, you can specify align-items: flex-start.
https://jsfiddle.net/3s2hLv92/1/

How to stop mobile safari from setting fixed positions to absolute on input focus?

Disclaimer - I understand there exists questions around fixed elements in safari, and fixed elements weren't supported, but now are and so forth. However I can't find a question that addresses this exact question.
Given the simplest of fixed sidebars, something like:
.sidebar {
position: fixed;
top: 10px;
right: 10px;
}
And a relatively long page, with input elements.
When an input element is focused, any fixed element becomes absolute - I understand the why, safari is trying to declutter the viewport - thats fine, but not always appropriate. I ask that I get to choose the best experience for the user (i know best naturally).
So the Question..
Is there any way to leave fixed elements as fixed even when input elements are focused?
I have attempted to do a bit of $(window).on('scroll', magic and position elements manually on scroll, but its quite jittery on the ipad.
Safari has supported position: fixed since at least version 9.2, but if you're seeing difficult issues, you can fully create the fixed position effect by making the document element and body full screen and then using absolute positioning. Scrolling then occurs in some main container element rather than the body. Your "fixed" elements can exist anywhere in the markup using this method.
jsfiddle here
html,
body,
.mainContainer {
height: 100%;
width: 100%;
overflow: hidden;
margin: 0;
}
.mainContainer {
overflow: auto;
}
.fixed {
position: absolute;
bottom: 20px;
left: 20px;
}
In order to achieve the effect you desire you need to change your approach to the layout. Instead of positioning the sidebar with position:fixed you need to use position:absolute within a position:relative container that is set to the height of the viewport within that position:relative container you need another div that uses overflow-y: scroll and -webkit-overflow-scrolling : touch
Caveat: I generally avoid using position fixed on tablet & mobile if possible although the browser support is there, in my experience it'll be janky and javascript solutions leave a lot to be desired, my first response would be to challenge the pattern with the designer. If I'm given designs that include a position fixed element when there are input elements, I'm more likely to seek a design solution than a development one as the focus issues you're describing are difficult to circumvent and maintain a quality user experience.
THE MARKUP:
<div class="outer">
<div class="sidebar">
<ul>
<li>Dummy list nav or something</li>
</ul>
</div>
<div class="container">
<input type="text" />
<!-- I added 10000 inputs here as a demo -->
</div>
</div>
THE CSS:
html,body{
-webkit-overflow-scrolling : touch !important;
overflow: auto !important;
height: 100% !important;
}
.outer {
position: relative;
overflow: hidden;
/* I'm using Viewport Units here for ease, but I would more likely check the height of the viewport with javascript as it has better support*/
height: 100vh;
}
.sidebar {
position: absolute;
top: 10px;
right: 10px;
/*added bg colour for demo */
background: blue;
}
.container {
height: 100vh;
overflow-y: scroll;
-webkit-overflow-scrolling: touch
}
input {
display: block;
}
Here's a CodePen for you to open in your simulator (presentation view):
https://codepen.io/NeilWkz/full/WxqqXj/
Here's the editor view for the code:
https://codepen.io/NeilWkz/pen/WxqqXj

Resizing divs and background images to fit page with CSS

Say that i want to have a couple of divs on my page with images in the background (like this: http://www.ubudhanginggardens.com/). I know how to set the size of my divs, but the problem is that the background image stays the same if I make the web browser smaller... I want the background image to scale up/down with the web browser.
CSS
body, html {
height: 100%;
width: 100%;
margin: 0px;
}
#container1 {
float: left;
height: 100%;
width: 50%;
background-image: url(../img/1.png);
}
#container2 {
float: left;
height: 100%;
width: 50%;
background-image: url(../img/2.png);
}
This can be done with pure CSS and does not even require media queries.
To make the images flexible, simply add max-width:100% and height:auto. Image max-width:100% and height:auto works in IE7, but not in IE8 (yes, another weird IE bug). To fix this, you need to add width:auto\9 for IE8.
Source
CSS:
img {
max-width: 100%;
height: auto;
width: auto\9; /* ie8 */
}
And if you want to enforce a fixed max width of the image, just place it inside a container, for example:
<div style="max-width:500px;">
<img src="..." />
</div>
jsFiddle example here. No javascript required. Works in latest versions of Chrome, Firefox and IE (which is all I've tested).
If you would like to have your image scale with your browser, set the width to a percent instead of defining it as a number of pixels.
So if you wanted the image to always cover half of a div:
<div class="my_div">
<img src="http://example.com"></img>
</div>
<style>
.my_div .image {
width:50%;
}
</style>
As you change your browser window size, the size of the image will change. You might want to take a look at Responsive CSS Frameworks, such as Twitter's Bootstrap, which can help you achieve exactly this behavior.

How can I resize an image dynamically with CSS as the browser width/height changes?

I wonder how I could make an image resize along with the browser window, here is what I have done so far (or download the whole site in a ZIP).
This works okay in Firefox, but it has problems in Chrome: the image does not always resize, it somehow depends on the size of the window when the page was loaded.
This also works okay in Safari, but sometimes the image is loaded with its minimum width/height. Maybe this is caused by the image size, I am not sure. (If it loads okay, try to refresh several times to see the bug.)
Any ideas on how could I make this more bulletproof? (If JavaScript will be needed I can live with that, too, but CSS is preferable.)
This can be done with pure CSS and does not even require media queries.
To make the images flexible, simply add max-width:100% and height:auto. Image max-width:100% and height:auto works in IE7, but not in IE8 (yes, another weird IE bug). To fix this, you need to add width:auto\9 for IE8.
source: http://webdesignerwall.com/tutorials/responsive-design-with-css3-media-queries
CSS:
img {
max-width: 100%;
height: auto;
width: auto\9; /* ie8 */
}
And if you want to enforce a fixed max width of the image, just place it inside a container, for example:
<div style="max-width:500px;">
<img src="..." />
</div>
JSFiddle example here. No JavaScript required. Works in latest versions of Chrome, Firefox and IE (which is all I've tested).
2018 and later solution:
Using viewport-relative units should make your life way easier, given we have the image of a cat:
Now we want this cat inside our code, while respecting aspect ratios:
img {
width: 100%;
height: auto;
}
<img src="https://www.petmd.com/sites/default/files/petmd-cat-happy-10.jpg" alt="cat">
So far not really interesting, but what if we would like to change the cats width to be the maximum of 50% of the viewport?
img {
width: 100%;
height: auto;
/* Magic! */
max-width: 50vw;
}
<img src="https://www.petmd.com/sites/default/files/petmd-cat-happy-10.jpg" alt="cat">
The same image, but now restricted to a maximum width of 50vw
vw (=viewport width) means the image will be X width of the viewport, depending on the digit provided. This also works for height:
img {
width: auto;
height: 100%;
max-height: 20vh;
}
<img src="https://www.petmd.com/sites/default/files/petmd-cat-happy-10.jpg" alt="cat">
This restricts the height of the image to a maximum of 20% of the viewport.
window.onresize = function(){
var img = document.getElementById('fullsize');
img.style.width = "100%";
};
In IE onresize event gets fired on every pixel change (width or height) so there could be performance issue. Delay image resizing for few milliseconds by using javascript's window.setTimeout().
http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html
Set the resize property to both. Then you can change width and height like this:
.classname img{
resize: both;
width:50px;
height:25px;
}
Are you using jQuery?
Because I did a quickly search on the jQuery plugings and they seem to have some plugin to do this, check this one, should work:
http://plugins.jquery.com/project/jquery-afterresize
EDIT:
This is the CSS solution, I just add a style="width: 100%", and works for me at least in chrome and Safari. I dont have ie, so just test there, and let me know, here is the code:
<div id="gallery" style="width: 100%">
<img src="images/fullsize.jpg" alt="" id="fullsize" />
prev
next
</div>
Initially, I was using the following html/css:
img {
max-width: 100%;
height: auto;
width: auto\9; /* ie8 */
}
<div>
<img src="..." />
</div>
Then I added class="img" to the <div> like this:
<div class="img">
<img src="..." />
</div>
And everything started to work fine.
Just use this code. What most are forgeting is to specify max-width as the max-width of the image
img {
height: auto;
width: 100%;
max-width: 300px;
}
You can use CSS3 scale property to resize image with css:
.image:hover {
-webkit-transform:scale(1.2);
transform:scale(1.2);
}
.image {
-webkit-transition: all 0.7s ease;
transition: all 0.7s ease;
}
Further Reading:
CSS3 2D Transforms
CSS3 Hover Effect Transitions, Transformations, Animations
Try
.img{
width:100vw; /* Matches to the Viewport Width */
height:auto;
max-width:100% !important;
}
Only works with display block and inline block, this has no effect on flex items as I've just spent ages trying to find out.

Resources