CSS grid doesn't seem to work properly on mobile devices - css

I want to use a simple layout, that consists of
An image
Some text
The text should be on the bottom and all remaining space should be used by the image. It seemed a simple task, but it has been a frustrating journey. Finally, I nailed but this solution doesn't work on mobile devices (Android and/or Chrome).
JSFiddle here
It looks like this on the desktop:
Unfortunately, the iPad renders it like this:
The text is barely visible, because the image took all the space. On Android (with Chrome 65 installed) it shows some of the text, but not all of it.
I use the following HTML code
<html>
<body>
<h1>TEST 123</h1>
<div class="wrapper img-top">
<img class="image" src="..." />
<div class="text">
<h2>Header</h2>
<p>...</p>
</div>
</div>
</body>
</html>
The relevant parts of the CSS looks like this (full code on JSFiddle):
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
height: 100vh;
overflow: hidden;
}
.wrapper {
display: grid;
grid-gap: 10px;
height: calc(100vh - 85px);
margin-bottom: 20px;
text-align: center;
align-items: center;
}
.wrapper.img-top {
grid-template-rows: 1fr auto;
}
.wrapper.img-top .image {
grid-row: 1;
justify-self: center;
}
.wrapper.img-top .text {
grid-row: 2;
justify-self: center;
}
.wrapper img.image {
max-height: 100%;
max-width: 100%;
}
I guess that there is a problem with the automatic image sizing, but I don't know what to do next? I want to have it responsive, but it just is not going to work.

Your problem is that you put fixed height on img-top. Your img is, let's say, 900 px, it's not the same on screen as iPad and desktop. Since you put your image to be 1 fr of height, it is getting bigger as screen is getting smaller. So you have two solutions, as far as I can tell, first is to restrict the size of your image, max-height: 300px;, or try putting overflow auto on .img-top.

Thanks #Jakub Muda for the suggestion about using flexboxes. I have finally fixed the problem by moving to a flexbox and fix the remaining issues.
After switching to a flexbox, I kept the same problem. The image was sized to 100% of the size of the parent wrapper div. I have fixed this by adding overflow: hidden to the image, so it will not overflow. This worked fine, but some images were distorted, because the aspect-ratio wasn't properly maintained. Adding object-fit: contain fixed this issue.
The complete sample can be found at JSFiddle, but for completeness I have added the CSS here as well:
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
height: 100vh;
overflow: hidden;
}
.wrapper {
display: flex;
flex-direction: column;
height: calc(100vh - 85px);
margin-bottom: 20px;
text-align: center;
align-items: center;
}
.wrapper .image {
justify-self: center;
flex: auto;
overflow: hidden; /* Important to make sure the image stays within bounds */
object-fit: contain; /* Important to make sure the image keeps its aspect ratio */
}
.wrapper .text {
justify-self: center;
flex-basis: none;
padding-top: 10px;
}
.wrapper img.image {
max-height: 100%;
max-width: 100%;
}

Related

CSS: My div needs to sit at the bottom of it's wrapping div! Not just the view-able screen

Hope you are well,
The following image highlights my CSS problem. The white bordered div with 'Contact' in the middle, I want to stick to the bottom of the screen.
Here is the CSS applied to that div as well as it's wrapper div! Note. I'm having this problem after the media queries are applied.
<div className='wrapperLanding'>
<div className="contentWrapper">
<p className="content">Illumination AI is a start-up studio that is focused on applying AI and ML to novel combinations of data across a diverse range of industries.</p>
<a className="contact" href="mailto:info#illumination.ai?subject=illumination20%AI%20Site%20Contact%20Inquiry">Contact</a>
</div>
</div>
/* contentWrapper is the child of wrapperLanding */
.wrapperLanding{
background-image: url("../images/lighthouseBackdrop.jpg");
height: 100vh;
background-size: cover;
background-position: center;
display: flex;
align-items: center;
flex-direction: column;
}
.contentWrapper{
position: absolute;
bottom: 3%;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
#media (max-height: 700px) {
html,
body{
overflow-y: visible;
}
.wrapperLanding{
height: 700px;
}
.contentWrapper{
/* position: fixed; */
bottom: 3%;
}
}
You may have noticed I have 'position: fixed;' commented out. With it applied, it still doesn't quite deliver the desired effect, as demonstrated below.
The problem here, is that while the image is stuck to the bottom of the user's view... it is NOT stuck to the bottom of the wrapping div! Any suggestions?
Thanks for your time!

How Do I Make the Footer Stay at the Bottom of Every Page without Many Classes?

I want to make the footer stay at the bottom of every page without making so many classes.
What I need is a footer that stays at the bottom of every page, no matter if the content is too scarce, without being "sticky," or using position: fixed.
I've done my research and looked at other answers on other questions but they've either got so many classes, they use position: fixed, or they use JS.
Here's the code for the layout.pug file:
.footer-wrapper
footer © 2018 Demo Website
And the code that I tried in SCSS is here:
.footer-wrapper {
// min-height:100%;
position: relative;
display: flex;
flex-direction: column;
flex: 1;
}
footer {
background-color: #0A0A0A;
color: white;
// height: 60px;
bottom: 0;
text-align: center;
position: absolute;
width: 100%;
padding: 1.5rem;
// display: grid;
// margin-top: auto;
// padding:10px;
}
Thanks a lot!
Something like this should work. Let flex-grow property handle the height of the .content container.
<div class="main">
<div class="header">header</div>
<div class="content">content</div>
<div class="footer">footer</div>
</div>
<style>
.main {
display: flex;
flex-direction: column;
justify-content: space-around;
height: 100vh;
}
.content{ flex-grow: 1; }
</style>
There's a really cheap way of doing this, which is actually quite good.
Assuming you're using a header as well, you could do something like this:
<header>
<div id = "body">
<footer>
...
<style scoped = "scss">
#body {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
margin-top: <header_height>;
margin-bottom: <footer_height>;
}
</style>
Basically it sets the body content to fill up the entire page, but leaves room for the header at the top of the page, and room for the footer at the bottom of the page (if there is no flexing). When there is not enough room to fit the body content on the page, the body div will flex in the column, automatically moving the footer with it.
Hope this helps!

How to make an image responsive on PS4?

I was on the console viewing a site I was working on and noticed my banners looked off.
<div class="blog-post-featured-banner">
<img width="1600" height="900" src="#">
</div>
.blog-post-featured-banner {
height: 50vh;
overflow: hidden;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.blog-post-featured-banner img {
width: 100%;
height: auto;
}
It looks fine on desktop, but when I view it on my PS4 it looks like the img had height:100%;, it looked squished. I expected it to behave the way it does on desktop, it takes 100% width of the screen and the height is hidden in the overflow. Given I'm viewing it on a TV I expected it to get a bit pixelated. Could it just be needing a very large image? The TV is 55".
Sort of a side question, but in the div that holds the image, I was trying to make the image vertically and horizontally centered in the "frame", how could I adjust my css to do so, if possible.
The browser that Playstation use might not support viewport units. The viewport units are gaining support on all modern browsers, however, there are some cases where this unit is not supported or bugs have been found.
Try setting the html and body tag's height to 100%. Then set your "blog-post-featured-banner" height to 50%. This should replicate what you are trying to achieve currently.
<div class="blog-post-featured-banner">
<img width="1600" height="900" src="#">
</div>
html, body {
height: 100%
}
.blog-post-featured-banner {
height: 50%;
overflow: hidden;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.blog-post-featured-banner img {
width: 100%;
height: auto;
}
I had a friend look at this. My side question sort of led to the answer, not saying what you guys answered was incorrect, but this did what I wanted.
<div class="blog-post-featured-banner">
<div class="featured-banner" style="background: url(<?php the_post_thumbnail_url( 'full' ); ?> ) no-repeat center center; background-size: cover;">
</div>
.blog-post-featured-banner {
height: 50vh;
overflow: hidden;
position: relative;
}
.featured-banner {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
The 50vh seemed to work on the PS4's browser.

CSS Stick Footer to Bottom

Here is my code to stick the footer to bottom of the page:
#footer {
background-color: #0F2157;
width: 100%;
bottom: 0px;
min-height: 35px;
padding-top: 5px;
}
When I'm doing it with height it works perfectly fine, but when I'm trying to set the minimum height it leaves a little space under the footer. Any guess how to fix that?
First of all, the height of body, html and container (see element with class 'container') has to have height: 100%;
In this solution I have used flex box. It is supported by all modern browsers and IE11.
It's necessary to add the following properties to container:
display: flex;
flex-direction: column; /*the flex items are placed in column, by default it is in row*/
To move footer to bottom, just add to flex item
margin-top: auto; /* it grabs all free space between flex items and put it before this flex item */
html, body {
height: 100%;
}
.container {
height: 100%;
background-color: green;
display: flex;
flex-direction: column;
}
.header {
height: 20%;
background-color: yellow;
}
.content {
background-color: white;
}
.footer {
min-height: 20%;
background-color: blue;
margin-top: auto;
}
<div class="container">
<div class="header">Header</div>
<div class="content">It's content</div>
<div class="footer">Footer in bottom</div>
</div>
What about using Flexbox? It is supported by IE>=10.
To use that, you have to split your page at least in two separated elements: The "upper"-one (.content) with the whole content of your page and the footer.
The "upper"-one gets the value flex: 1, which is a shorthand for:
flex-grow: 1
flex-shrink: 1
flex-basis: auto
This means, that the "upper"-element could grow to the maximum, while the footer reserves only it's actually required space.
Code snippet
html {
height: 100%;
}
body {
min-height: 100%;
margin: 0;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
}
<!doctype html>
<html>
<head>
</head>
<body>
<div class="content"></div>
<footer class="footer">
Hey footer!
</footer>
</body>
</html>
You used min height 35 px. I think your content's height inside of footer is more than 35px. So check the margin or padding of all footer elements.
It will be better, if you can make a jsfiddle demo.
[SOLVED]
I found this to be working for my example:
#footer {
position: absolute;
bottom: 0;
width: 100%;
}

How can I have a position: fixed; behaviour for a flexbox sized element?

I have a div called .side-el which I would like to have in a position: fixed; behavior, but as soon as I apply position fixed the width alternates from the right one. The right width would be the one set by flexbox. How can I achieve this goal?
.container {
-webkit-align-content: flex-start;
align-content: flex-start;
-webkit-align-items: flex-start;
align-items: flex-start;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-justify-content: flex-start;
justify-content: flex-start;
* {
box-sizing: border-box;
-webkit-flex-grow: 1;
flex-grow: 1;
-webkit-flex-shrink: 0;
flex-shrink: 0;
}
}
.main-el {
box-sizing: border-box;
padding:0 2em;
width: 70%;
}
.side-el {
box-sizing: border-box;
width: 30%;
}
<div class="container" style="background-color: blue; height: 100px;">
<div class="main-el">
<div style="background-color: red; height: 1000px;">content</div>
</div>
<div class="side-el" >
<div style="background-color: red; height: 100px;">content</div>
</div>
</div>
Here's a way to do this inspired by bootstrap:
.fixed-top {
display: flex;
position: fixed;
top: 0;
left: 0;
right: 0;
}
This gives your flex-box room to breathe and do it's flex-box thing. If your flex-direction is column, you could use top, left, bottom instead.
This works because when you give an element a fixed position and a left and right of 0 or a top and bottom of 0, the element is stretched to fill the space from left to right, or top to bottom. That in turn allows a flex-box to use the amount of space you would expect without position fixed.
You can't.
As explained by the CSS2.1 spec:
Absolutely positioned boxes are taken out of the normal flow.
And the Flexible Box Layout spec confirms that:
An absolutely-positioned child of a flex container does not
participate in flex layout. However, it does participate in the
reordering step (see order), which has an effect in their
painting order.
(Emphasis mine)
#Daniel , I know this is very late but ... while the accepted answer is correct, I don't feel it's very helpful.
I had the same question (which is how I came across this post), and the solution I think I'll go with is to wrap the position fixed element within the flex element.
Here's a (very ugly) example
Relevant Markup
<aside class="Layout-aside" ng-class="{'isCollapsed': collapsed}" ng-controller="AsideCtrl">
<div class="Layout-aside-inner">
<button ng-click="collapsed = !collapsed">
<span ng-show="collapsed">></span>
<span ng-hide="collapsed"><</span>
</button>
<ul class="Layout-aside-content">
<li ng-repeat="i in items">{{i}}</li>
</ul>
</div>
</aside>
Relevant CSS
.Layout-aside {
order: 0;
min-width: 140px;
width: 140px;
background-color: rgba(0, 255, 0, .4);
transition: width .4s, min-width .4s;
}
.Layout-aside.isCollapsed {
min-width: 25px;
width: 25px;
}
.Layout-aside-inner {
position: fixed;
}
.Layout-aside.isCollapsed .Layout-aside-inner {
width: 25px;
}
.Layout-aside.isCollapsed .Layout-aside-content {
opacity: 0;
}
position:sticky was mentioned by Juozas Rastenis above but without code example.
Here's a minimalist example:
* {
box-sizing: border-box;
}
body {
display: flex;
margin: 0;
}
nav {
width: 20%;
height: 100vh;
top: 0; /* this is required for "sticky" to work */
position: sticky;
background: lightblue;
padding: 1rem;
}
main {
height: 3000px; /* cause scroll */
background: lightpink;
flex-grow: 1;
padding: 1rem;
}
<body>
<nav>
sidebar here
</nav>
<main>
content here
</main>
</body>
You can achieve it with a css alternative position: sticky
It acts great but the only problem is browser support (June 2018):
https://caniuse.com/#feat=css-sticky
Hope it gets better soon.
A far simpler solution would be to use overflow-y:scroll and height: 100vh on the main-el container. This will give the appearance of fixed position to the side-el container without resorting to position: fixed.
You are saying you want position:fixed;-like behavior that plays together with flexbox. As mentioned in the accepted answer, applying this property to an element drops it out of the normal flow, so this isn't really possible.
If what you want is to have a fixed sidebar .side-el and a scrollable content box .main-el as the items of a flex container, here's how you might do this:
Disable scrolling in the flex container's parent; let's assume it's
<body>, as you don't provide div.container's parent. Also, hard-set
it's height to viewport-height (100vh) so that no part of the body's
box remains outside view (imagine the body's box normally extending
beyond your screen to contain the entire document; you don't want
that, if you are to disable the ability to move the viewport via
scrolling).
Set the flex container's (.container) height to that of it's parent.
Selectively re-enable scrolling for the content box (.main-el).
In CSS:
body{
overflow: hidden;
height: 100vh;
}
.container {
display: flex;
height: 100%;
}
.main-el {
overflow-y: auto;
}
You can achieve this without position: fixed; by just adding overflow: auto; and height: 100%; to the flex-item that contains the long content:
.container {
display: flex;
}
.main-el {
padding:0 2em;
width: 70%;
overflow: auto;
height: 100%;
}
.side-el {
width: 30%;
}
<div class="container" style="background-color: blue; height: 300px;">
<div class="main-el">
<div style="background-color: red; height: 1000px;">content</div>
</div>
<div class="side-el" >
<div style="background-color: red; height: 100px;">content</div>
</div>
</div>
I had the same issue, I actually just found a way to have flex-box, a width for the nav bar, and center it while in a fixed position.
nav {
display: flex;
height: 50px;
width: 90%;
left: 5%;
position: fixed;
}
I wanted to be able to have a flex-box nav bar in a fixed position but centered. So what I did was do the left 5% since that's equal to half of the 10% width left over. Try it out, it might help you! :)

Resources