Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
Agreeing on terms
By responsive images I mean techniques for picking a source image with optimal file size for a given screen (viewport size and DPI).
By responsive context I mean RWD: page components changing their layout based on viewport width.
The problem
These two goals are fairly easy to achieve independenlty. For responsive images we have <img srcset sizes> and <picture>, for responsive context we have the min-width and max-width media queries.
But how do I use both at once?!
Problem example
Let's say I have a component displaying three images and responding to viewport width like this:
You can see that as viewport size growth, image size does not grow linearly. It varies back and forth.
Ideally, different file sizes should be picked should load depending on CSS dimensions of each image, not screen width.
Examples:
for the "tablet portrait" viewport, the first image should pick a larger source than the other two;
"tablet landscape" viewport should load smaller images than "large phone" viewport, despite having a larger width.
Since responsive images are an HTML technique and RWD is a CSS technique, I don't see a graceful way to make them work together.
Hypothetical solution 0
Ideally, in order to achieve that, the sizes HTML attribute should vary depending on each image element width. But RWD is not capable of that.
I could imagine something like this:
/* full-width image and single-column grid */
.responsive-image {
sizes: 100vw;
}
/* 1+2 column grid aka "tablet portrait" layout */
#media (min-width: 400px) and (max-width: 767px) {
.grid .responsive-image {
sizes: 50vw;
}
.grid .responsive-image:first-child {
sizes: 100vw;
}
}
/* 3 column grid */
#media (min-width: 768px) {
.grid .responsive-image {
sizes: 33vw;
}
}
Boy, would this be awesome! A fully responsive grid, fully responsive images aware of their own context, compact CSS.
Unfortunately, that does not work. It is not possible to manipulate sizes from CSS.
This example is here only to demonstrate the desired outcome.
Potential solution 1: JavaScript magic
An obvious solution would be to use a JavaScript library to make the decision based on image element's own width (similar to the element query approach).
Pros:
Once set up, it just works! Very easy to add new images.
This approach is fully dynamic. Components are aware of their own width and pick correct file size regardless of context (size of the parent component).
Cons:
The images will start loading too late.
I have a single-page app with server-side pre-rendering. The server must provide an src for each image without knowing the viewport size.
On the one hand, this resolves the previous problem.
On the other hand, this will result in loading two sets of images when JS takes over. :(
Potential solution 2: CSS custom properties aka var()
I came up with the following idea, and I doubt I'm the first one to think about it.
Put all available image sources into CSS custom properties.
Use CSS var() inside media queries to pick the right one.
Example:
<div
class="responsive-image"
style="
--image-250: url('http://exmaple.com/image-250.jpg');
--image-500: url('http://exmaple.com/image-500.jpg');
--image-1000: url('http://exmaple.com/image-1000.jpg');
--image-1500: url('http://exmaple.com/image-1500.jpg');
--image-2000: url('http://exmaple.com/image-2000.jpg');
--image-5000: url('http://exmaple.com/image-5000.jpg');
>
.responsive-image {
background-image: var(--image-250);
}
#media (min-device-pixel-ratio: 1.5) and (max-width: 399px) {
/* full-width image */
.responsive-image {
background-image: var(--image-500);
}
/* single column grid layout */
.grid .responsive-image {
background-image: var(--image-500);
}
}
#media (min-device-pixel-ratio: 1.5) and (min-width: 400px) and (max-width: 767px) {
.responsive-image {
background-image: var(--image-1000);
}
/* 1+2 column "tablet portrait" grid layout */
.grid .responsive-image:first-child{
background-image: var(--image-1000);
}
.grid .responsive-image:not(:first-child){
background-image: var(--image-500);
}
}
/* ... */
Pros:
Works with pure CSS, no JS required.
Works well with server pre-rendering.
Cons:
Using <div> to render all images.
Nested responsive contexts are a lot of trouble. Media query rules can only be applied based on viewport width, not element width, but responsive images should be picked based on child element widths. As a result, the complexity of CSS rules grows exponentially as the depth of nesting grows. With one level of nesting (as in the example above), it's already unreasonably complicated. I don't even want to think about two levels of nesting.
Question
What are available solutions to this problem?
Of course, I'm hoping for a well-established approach without sub-optimal drawbacks.
But I want to gather here all less optimal ways of solving this as well: best practices, JS libraries, CSS techniques, anything.
Bonus question
Is it even worth doing?
Have there been any tendencies lately, e. g. articles advocating for not using responsive images, e. g. to avoid overhead and build for modern retina screens and 4G internet? After all, it's only a question of extra (milli)seconds of loading time, not denial of service.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to create a responsive webpage using bootstrap,but I'm confused on how to start.Can anyone help me to move into the right direction?
Here is my code
https://jsfiddle.net/c30a7bd2/It should be responsive for all the devices.
Despite the downvotes, here's some info to get you started.
Process:
Design from smallest viewport to biggest. i.e. design your responsive site first for mobile devices in portrait, then mobile landscape, then tablet portrait, then tablet landscape, then smallest desktop, then largest desktop. If you look at the Chrome dev tools, you will see an icon on the left-top to the right of the arrow icon. This puts the browser into responsive design mode that lists the most common devices. Very helpful.
Learn about media queries:
https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries
There is a lot of stupid confusion about how to use #media queries correctly. Let me set you straight right from the beginning.
You only need to worry about min-width. Don't think about ranges, don't use anything else other than min-width.
Here's why.
Since we're writing our css from the smallest device width first, as browser widths increase all we're doing is overriding earlier set styles. That's it. That literally is the secret to doing great, simple responsive css coding.
What breakpoints to use:
Again, lots of clever engineers try to be too clever. They introduce odd breakpoints, try to avoid pixel 'px' definitions, etc. Stop doing that.
Remember, since we're are writing our code mobile portrait first (the smallest device size), there is no media-query for this. Its just css.
Here's the breakpoints you should start with:
/* all mobile portrait coding goes first */
#media all and (min-width: 480px) {
/* this is the most common mobile landscape minimum width */
}
#media all and (min-width: 768px) {
/* this is the most common minimum tablet width */
}
#media all and (min-width: 1024px) {
/* this is the most common minimum desktop width. It also is the
most common minimum tablet landscape width. */
}
#media all and (min-width: 1300px) {
/* this is the most common minimum wide desktop width.
This is the only media query you might consider setting to 1200px
if your graphic design requires it. */
}
That's it. That is quite literally everything you know to get started writing great responsive css.
Just remember the key concept is utilizing inheritance. 80% of your css should probably be written for the mobile portrait size first. All of those styles get inherited into wider and wider screen widths. Then override them as necessary for the new wider screen. You will find that as your media queries increase, there is less and less css in them.
Have fun and write great code!
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I am always coming back to the same question when developing a website for all devices.
Does it make more sense to make everything full responsive by setting everthing in percentage values or to query a few max-width and min-width with css3 so you can have your normal website with 960px and size it down for the different devices..
For the css3 mediaqueries i would use something like this:
/* CSS */
/* Basic responsive */
#media screen and (max-width: 960px) {
/* ..custom CSS for viewports less than 960 here */
header { /*...*/ }
section { /*...*/ }
footer { /*...*/ }
/* etc.. */
}
/* iPads (portrait) and similar tablets */
#media only screen
and (min-device-width : 768px) {
header { /*...*/ }
section { /*...*/ }
footer { /*...*/ }
/* etc.. */
}
/* Smartphones */
#media only screen and (max-device-width : 480px) {
header { /*...*/ }
section { /*...*/ }
footer { /*...*/ }
/* etc.. */
}
thank you
You should do a bit of both. If you can write some CSS that works across all devices then that's great. For example if your header goes 100% of the width for every device there's no need to adjust it with media queries. In reality you'll find certain parts don't work and will need adjustment. This is where media queries come in.
You shouldn't treat each media query as a new stylesheet, instead it should just alter or build on the styles already defined in order to make the layout work.
Typically sites adopt a mobile-first approach. This means you start with the mobile layout and increase the complexity as the viewport width increases. The benefit of this is that older browsers will get the simplistic mobile version of the site (which at least should work, even if it isn't pretty on a desktop).
You can read more about responsive layouts here:
Build a Responsive, Mobile-Friendly Website From Scratch
Common Techniques in Responsive Web Design
If you fall in such confusions, i would suggest to opt for bootstrap
...otherwise, using media-queries is a better option as it gives you wider flexibility and freedom to set values both in pixels as well as percentages.
A combination of both, or media queries.
You have to remember that if you don't use Media Queries, on every device (smartphone, desktop, laptop, etc.) you are loading all data for the website.
And if you load all data it loads also, for ex. images and that can cost a lot of Kb sent to the client browser.
With Media Queries you can set display: none; to images on the page and less Kb will be send to the client.
So it is important to understand that form mobile devices you should send as small portion of data as possible.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I want to know how to make a website, and all of its elements responsive to adapt to different screen sizes: fonts, images etc...
I have done something like this:
#media only screen
and (max-width : 320px)
{
//here put the width and height of all the elements in the site
}
I have to specify target resolution for each one. Can there be a common setting that can apply to all resolution?
Can there be other ways to make it dynamic for each screen size? Is there an easier way?
Adaptive layouts (Responsive layouts) consists of the following three factors:
1. Flexible Layouts:
The divs you use to create your web page layouts need to consist of relative length units.
This means you shouldn't use fixed widths in your CSS, rather use percentages.
The formula to convert sizes from a design to percentages is (target/context)x100 = result
Lets take the picture above as an example of a design. To calculate what the size of the div on the left is going to be calculated like this:
(300px/960px)x100 = 30.25%
The CSS would look something like this:
.leftDiv
{
width: 30.25%;
float: left;
}
.rightDiv
{
width: 65%;
float: left;
}
For text to automatically resize you can use a unit called VW (ViewWidth)
.myText
{
font-size: 1vw;
}
This ensures that the text automatically resize relative to the view width.
2.Flexible Media:
Flexible media applies to images, videos and canvasses which automatically resize relative to its parent.
Example:
img, video, canvass
{
max-width: 100%;
}
This ensures that these elements resize automatically inside its parent.
3. Media Queries:
The next step is to use media queries like you've done in your question, these media queries define certain CSS statements for certain screen sizes. I normally use only three media queries for computers screens, tablets and phone screens. Its not necessary to have more than this because the Flexible Layouts and Flexible Media will ensure relative resizing if done correctly.
You may find this helpful: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries
There are two options I am aware of.
Use Adobe Reflow, which exactly what you have but the software writes it for you and you just click and drag your elements, so you will achieve the same result much faster.
Have absolutely everything a percentage, size, margins, borders, everything. This way you won't have to rewrite code over and over, a 'one size fits all' option.
Take a look at Bootstrap and more specifically the Grid System. It should help you with css for different screen sizes.
Incase if you are new to CSS adaptive layout please do have a look at the following websites:-
a) Bootstrap
b) Foundation
In my opinion Foundation, is a great place to start with.It has a very beautiful documentation about grids.Please do check it out
I've been working with a page which has two layouts dependent upon the width of the device being used to view the page:
/*Above is Mobile*/
#media screen and (min-device-width: 600px){
/*Below is Web*/
}
This approach essentially takes the various "web" and "mobile" divs throughout the page and displays, hides, or alters them as required for either layout; however, while the "web" divs are hidden, they are still loaded by the mobile device, potentially slowing down the page load.
My first thought was that if I could define only the "mobile" divs and not the "web" divs, then I could avoid loading all of these additional elements. Thus, does a method similar to the CSS media query exist for HTML? Or alternatively, is is there a way to define two different HTML layouts based on the width of the device the page is displayed on?
EDIT: A better approach, at least as far as images and graphics are concerned, is likely to use CSS to define the image rather than the HTML. Thus, instead of doing:
<div id="img"><img src="URL"></div>
...and trying to hide the div, you would instead take this approach:
<div id="img"></div>
and...
div#img {
background: none;
}
/*Above is Mobile*/
#media screen and (min-device-width: 600px){
/*Below is Web*/
div#img {
background: url(URL);
height: 400px;
width: 600px;
}
}
Thus, the mobile version doesn't load the images and we're still only using CSS.
Or alternatively, is is there a way to define two different HTML
layouts based on the width of the device the page is displayed on?
Thats the route to take imho. HTML doesn't have a similar mechanism to define different rulesets for viewports.
I think there are some js options. Does this conversation help?
What is the best way to detect a mobile device in jQuery?
Check out this page:
http://new.brixwork.com/realtors/real-estate-website-features
Below the big computer screen, the images and text blocks alternate in a staircase design.. on one div the image is on the right, on another, on the left. And there are 4 blocks.
I'm using the Skeleton framework (www.getskeleton.com) for a responsive grid design, so the grid re-sizes on the viewport queries, which is great. however this poses a problem on iphones or vertical view on iPads when the image & text boxes shuffle to get on top of each other.
Instead of
image text
text image
image text
text image
I get
image
text
text
image
image
text
text
image
Because of the order by which the objects were typed out in my HTML.
So the question is, is there a clever way to re-position items via CSS? I already use media queries like this:
#media only screen and (max-width: 959px) {
}
/* Tablet Portrait size to standard 960 (devices and browsers) */
#media only screen and (min-width: 768px) and (max-width: 959px) {
}
/* All Mobile Sizes (devices and browser) */
#media only screen and (max-width: 767px) {
}
/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
#media only screen and (min-width: 480px) and (max-width: 767px) {
}
/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
#media only screen and (max-width: 479px) {
}
Any ideas? I want to do this without resorting to jQuery to detect the window size and re-size them if I can avoid it. I can't use PHP to alter the DIV orders on "echo", because I want the re-shuffling to be done effectively if a tablet is taken from horizontal to a vertical position.
Where there's a will, there's a way! The big drawback with using a framework that uses semantics like "six columns alpha" and "ten columns omega" is that they create an expectation for visual ordering. The six columns are on the left, the ten columns are on the right, and the alpha/omega naming conventions affect margins because the order is right in the markup. You have stumbled across an unexpected use case for the author, I'm thinking.
(Incidentally, your ten column area also contains images that are overflowing their containers; ie. they're not being resized)
The straight goods:
My honest advice for future maintainability is to learn from skeleton, take what you want from it understanding what its different classes do... and re-invent it.
For example, what you have on your main page are a series of feature containers. The markup should look consistent, like this:
<div class="featurebox">
<div class="media">Image, slider, or other visual interest items here</div>
<div class="items">Text of items of interest</div>
</div>
<div class="featurebox">
<div class="media">A different image, slider, etc</div>
<div class="items">More text of items of interest</div>
</div>
And then you can style these to create the left-right effect. The key here is in the selectors. By floating right instead of left for divs inside every other featurebox, our effect is easily achieved:
.featurebox { width: 600px; overflow: hidden; clear: both;}
.featurebox div { float: left; }
.featurebox:nth-of-type(odd) div { float: right; }
.items { width: 200px }
.media {background-color: grey; width:400px; height: 100px;}
Fiddle: http://jsfiddle.net/7qRfh/
The problem in modifying what you currently have is that this doesn't really fit skeleton's expectation of left-to-right stacking of floats. If you're willing to say "phooey" you could identify your containers, target every second one, and flip the .columns float orientation. You will also need to override omega and alpha class behaviour so that omega is actually acting like alpha and vice versa. A mess, in my opinion, but it'll work.
The hack
I just had a fiddle around here and I think I closed it. Can't find the URL in my history so I may not have saved it first. :-/
But no matter. It boiled down to this: you can do what you need to do with your current markup, but the changes to CSS are even more extensive and become nutty.
The container already has position: absolute, so you have to unfloat the "six" and "ten" columns, position them absolutely, with "ten" on top and "six" on the bottom. The big issue is that do to it easily, the container as well as the "six" and "ten" all need to have height set on them. Absolute positioning takes an element out of document flow, so without height it just becomes an overlapping weird mess.
Honestly, if you insist on skeleton the way it is, and the markup the way it is, the most reasonable hack actually turns out to be JavaScript. If you already have jQuery on your page, all the easier.