Showing posts with label responsive-design. Show all posts
Showing posts with label responsive-design. Show all posts

Friday, July 27, 2018

Set width/height of image to avoid reflow on image load

Leave a Comment

When I use image tags in html, I try to specify its width and height in the img tag, so that the browser will reserve the space for them even before the images are loaded, so when they finish loading, the page does not reflow (the elements do not move around). For example:

<img width="600" height="400" src="..."/> 

The problem is now I want to create a more "responsive" version, where for the "single column case" I'd like to do this:

<img style="max-width: 100%" src="..."/> 

but, if I mix this with explicitly specified width and height, like:

<img style="max-width: 100%" width="600" height="400" src="..."/> 

and the image is wider than the available space, then the image is resized ignoring the aspect ratio. I understand why this happens (because I "fixed" the height of the image), and I would like to fix this, but I have no idea how.

To summarize: I want to be able to specify max-width: 100%, and also somehow make sure the content is not reflowed when the images are loaded.

8 Answers

Answers 1

I'm also looking for the answer to this problem. With max-width, width= and height=, the browser has enough data that it should be able to leave the right amount of space for an image but it just doesn't seem to work that way.

I worked around this with a jQuery solution for now. It requires you to provide the width= and height= for your <img> tags.

CSS:

img { max-width: 100%; height: auto; } 

HTML:

<img src="image.png" width="400" height="300" /> 

jQuery:

$('img').each(function() {      var aspect_ratio = $(this).attr('height') / $(this).attr('width') * 100;     $(this).wrap('<div style="padding-bottom: ' + aspect_ratio + '%">'); }); 

This automatically applies the technique seen on: http://andmag.se/2012/10/responsive-images-how-to-prevent-reflow/

Answers 2

At first I would like to write about the answer from october 2013. This was incomplete copied and because of them it is not correct. Do not use it. Why? We can see it in this snippet (scroll the executed snippet to the bottom):

$('img').each(function() {       var aspect_ratio = $(this).attr('height') / $(this).attr('width') * 100;      $(this).wrap('<div style="padding-bottom: ' + aspect_ratio + '%">');  });
img { max-width: 100%; height: auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>  <div style="width:300px;border:1px solid red">  <img width="400" height="300" src="data:image/png;base64,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"/>  Some text  </div>

And we can see the text is afar from bottom. What is in this example incomplete/ incorrect? I will show it with correct example with pure JavaScript (we do not need to download jQuery for that).

Correct example with pure JavaScript

Please scroll the executed snippet to the bottom.

var imgs = document.querySelectorAll('img');  for(var i = 0; i < imgs.length; i++)  {      var aspectRatio = imgs[i].getAttribute('height') /                        imgs[i].getAttribute('width') * 100;        var div = document.createElement('div');      div.style.paddingBottom = aspectRatio + '%';      imgs[i].parentNode.insertBefore(div, imgs[i]);      div.appendChild(imgs[i]);  }
.restrict-container div{position:relative}  img  {      position:absolute;      max-width:100%;      top:0; left:0;      height:auto  }
<div class="restrict-container" style="width:300px;border:1px solid red">      <img width="400" height="300" src="data:image/png;base64,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"/>      Some text<br>      <img width="400" height="300" src="data:image/png;base64,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"/>      Some text  </div>

The mistake from answer from october 2013: the image should be placed absolute (position:absolute) to the wrapped container but it is not so placed.

This is the end of my answer to this question.


For further information read more about:

Answers 3

For a css only solution, you can wrap the img in a container where the padding-bottom percentage reserves space on the page until the image loads, preventing reflow.

Unfortunately, this approach does require you to include the image aspect ratio in your css (but no need for inline styles) by calculating (or letting css calculate for you) the padding-bottom percentage based on the image height and width.

If many of your images can be grouped into a few standard aspect ratios, then you could create a class for each aspect ratio to apply the appropriate padding-bottom percentage to all images with that aspect ratio. This may save you a little time and effort if you are not dealing with a wide variety of image aspect ratios.

Following is some example html and css for an image with a 2:1 aspect ratio:

HTML

<div class="container">   <img id="image" src="https://via.placeholder.com/300x150" /> </div> 

CSS

.container {   display: block;   position: relative;   padding-bottom: 50%; /* calc(100%/(300/150)); */   height: 0; }  .container img {   position: absolute;   top: 0;   left: 0;   width: 100%;   height: 100%; } 

The snippet below adds some extra html, css and javascript to create some visual top and bottom reference points and mimic a very slow loading image so you can visually see how the reflow is prevented with this approach.

const image = document.getElementById('image');  const source = 'https://via.placeholder.com/300x150';  const changeSource = () => image.src = source;    setTimeout(changeSource, 3000);
.container {    display: block;    position: relative;    padding-bottom: 50%; /* calc(100%/(300/150)); */    height: 0;  }    .container img {    position: absolute;    top: 0;    left: 0;    width: 100%;    height: 100%;  }    .top, .bottom {    background-color: green;    width: 100%;    height: 20px;  }
<div class="top"></div>  <div class="container">    <img id="image" src="" />  </div>  <div class="bottom"></div>

Answers 4

From this blog post by Jonathan Hollin: add the image's height and width as part of an inline style. This reserves space for the image, preventing reflow when the image loads, but it's also responsive.

HTML

<figure style="padding-bottom: calc((400/600)*100%)">   <img src="/images/kitten.jpg" /> </figure> 

CSS

figure {   position: relative; }  img {   max-width: 100%;   position: absolute; } 

The figure can be replaced with a div or any other container of your choice. This solution relies on CSS calc() which has pretty wide browser support.

Working Codepen can be seen here.

UPDATE:

I found a much cleverer alternate version of this: http://cssmojo.com/aspect-ratio-using-custom-properties-and-calc/. This still requires a wrapper element and it requires CSS custom properties, but I think it's much more elegant. Codepen example is here (credit to Chris Coyier's original).

Answers 5

I want to develop further my answer, and address the original question asked in May 31 '13 at 6:27 by gabor and it says:

Set width/height of image to avoid reflow on image load. I would like to fix this, but I have no idea how. To summarize: I want to be able to specify max-width: 100%, and also somehow make sure the content is not reflowed when the images are loaded.

Also I want to address de most recent request made by Ry- and it says:

This question has not received enough attention. Can this be done any better in 2018?

Now to make the answer even more clear the meaning of "somehow" acording with the Cambridge dictionary is as follows.

For English: someway in a way or by some means that is not known or not stated.

For American English: in a way which is not known or not stated.

Under this context I managed to somehow make it work using modern CSS and HTML5 Semantic Elements wich are considered some of the best Practices for 2018 acording to this article 30 Best HTML5 Practices 2018

Taking all of that in to consideration the resulting code shows the expected behaviour.

@charset "UTF-8";  :root{    --w:#fff;    --x:100%/600;    --bu:#e15f41;      --m:#786fa6;    --v:400;    --n:#f8a5c2;    --z:400/600;    --t:#333;    --r: calc(var(--z)*100%);    --b:#000;  }    body{    margin: 1rem;  	padding: 0;  	border: 0;    outline: 0;  	font-size: 100%;  	font: inherit;    color: var(--t);  	vertical-align: baseline;    box-sizing: border-box;    font-family: sans-serif;    background-color: var(--b);    min-width: 100px;    display: grid;  }  nav{    text-align: center;    background-color: var(--n);    padding: .3rem;  }  h1, h2, h3{    color: var(--w);  }  ul{    display: grid;    grid-template-columns: repeat(5, 1fr);    list-style: none;    padding: .2rem;  }  a{text-decoration: none; color: var(--b);}  a:hover{color:var(--w);text-shadow: 1px 1px 3px var(--t);}  main{    display: grid;    min-width: 100px;    background-color: var(--m);    padding: 1em;  }    figure{    --i:calc(var(--x)*var(--v));    margin: 0;    position: relative;        border: 4px solid white;    padding-top: var(--i);  }  img{    position: absolute;    top: 0px;    left: 0px;    max-width: 100%;    height: 100%;  }      @media only screen and (min-width: 600px){    main{      padding: 1.5em;      min-width: 100px;      background-color: var(--m);      display: grid;      grid-template-columns: repeat(2,1fr);      grid-gap: .5em;    }  }    @media only screen and (min-width: 1080px){    main{      padding: 2em;      min-width: 100px;      background-color: var(--m);      display: grid;      grid-template-columns: repeat(3,1fr);      grid-gap: .8em;    }  }
<!DOCTYPE html>  <html lang="en">  <head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <meta http-equiv="X-UA-Compatible" content="ie=edge">  <link rel="stylesheet" href="master.css">  <title>Document</title>  </head>  <body>    <header>          <nav>            <h1>site title</h1>            <ul class=''>              <li><a href="#">menu1</a></li>              <li><a href="#">menu2</a></li>              <li><a href="#">menu3</a></li>              <li><a href="#">menu4</a></li>              <li><a href="#">menu5</a></li>            </ul>          </nav>    </header>      <main>        <section>          <h3>Random Title</h3>          <figure>            <img class="on-off" src="" alt="image not found">          </figure>          <article><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></article>        </section>        <section>          <h3>Random Title</h3>          <figure>            <img class="on-off" src="" alt="image not found">          </figure>          <article><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></article>        </section>        <section>          <h3>Random Title</h3>          <figure>            <img class="on-off" src="" alt="image not found">          </figure>          <article><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></article>        </section>        <section>          <h3>Random Title</h3>          <figure>            <img class="on-off" src="" alt="image not found">          </figure>          <article><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></article>        </section>        <section>          <h3>Random Title</h3>          <figure>            <img class="on-off" src="" alt="image not found">          </figure>          <article><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></article>        </section>        <section>          <h3>Random Title</h3>          <figure>            <img class="on-off" src="" alt="image not found">          </figure>          <article><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></article>        </section>        <section>          <h3>Random Title</h3>          <figure>            <img class="on-off" src="" alt="image not found">          </figure>          <article><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></article>        </section>        <section>          <h3>Random Title</h3>          <figure>            <img class="on-off" src="" alt="image not found">          </figure>          <article><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></article>        </section>        <section>          <h3>Random Title</h3>          <figure>            <img class="on-off" src="" alt="image not found">          </figure>          <article><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></article>        </section>      </main>    <footer>              </footer>  </body>  </html>

Aditionally you can see how it works on codepen. GO TO CODEPEN

Answers 6

If I understand the requirements ok, you want to be able to set an image size, where this size is known only on content (HTML) generation, so it can be set as inline styles.

But this has to be independent of the CSS, and also prior to image loading, so also independent from this image sizes.

I have come to a solution tha involves wrapping the image in a div, and including in this div an svg that can be set to have proportions directly as an inline style.

Obviously this is not much semantic, but at least it works

The containing div has a class named img to show that it , well, should be an img

To try to reproduce the loading stage, the images have a broken src

.container {    margin: 10px;    border: solid 1px black;    width: 200px;    height: 400px;    position: relative;  }    .img {    border: solid 1px red;    width: fit-content;    max-width: 100%;    position: relative;  }    svg {    max-width: 100%;    background-color: lightgreen;    opacity: 0.1;  }    #ct2 {    width: 500px;  }    .img img {    position: absolute;    width: 100%;    height: 100%;    max-height: 100%;    max-width: 100%;    top: 0px;    left: 0px;    box-shadow: inset 0px 0px 10px blue;  }
<div class="container" id="ct1">      <div class="img">          <svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 400 300" width="400">          </svg>        <img width="400" height="300" src="missing.jpg">      </div>  </div>  <div class="container" id="ct2">      <div class="img">          <svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 40 30" width="400">          </svg>        <img width="400" height="300" src="missing.jpg">      </div>  </div>

Answers 7

<div style=" background-image:url('./media_assets/back1.gif'); background-size: cover; width: 100%; height: 500px; background-position: center; background-repeat: no-repeat;"> 

using image as a div background may solve your problem. this works well for responsive design

Answers 8

for responsive html wrap you image with a div fix only width of the div.

css

.imgPan{     width:200px;     } .imgPan img{     max-width:100%;     height:auto; } 

html

<div class="imgPan">    <img src="..."/> </div> 

now image will re-size in the aspect ratio.

Read More

Sunday, June 10, 2018

Responsive design with vmin and mobile address bars

Leave a Comment

I am trying to create a number of square divs next too each other (which can expand in height if there is too much text..but most of the time there will not be too much text). I am trying to set it up in a responsive fashion.

When scrolling on the page, the address bar in my mobile browser keeps appearing and disappearing. When this happens when the phone is in landscape mode the dimensions change every time the address bar comes on or goes off. This creates a very annoying user experience.

My HTML code has the following viewport line in it:

<meta name="viewport" content="width=device-width, initial-scale=1.0"> 

My code looks like this:

.block {         width: 80vmin;         min-height: 80vmin;         margin: 5% auto;         border-radius: 15vmin;         padding: 20px 10px;  } 

Obviously, the culprit is the vmin component. If I do not specify vmin then the boxes are way too large when viewed in landscape mode.

Is there a way to get vmin to ignore the address bar and pretend it is not there? If not, what other options do I have to solve this problem?

2 Answers

Answers 1

Chrome as of the bad UX added the feature of counting the vh, vmin etc. values only after hiding the addressbar. This way the browser won't count them too many times, and the fps will not drop, but the jumping effect will appear.

I would use grid if I were you. You can use min-content height and the boxes will be the same high. With the repeat, auto-fill and minmax use can add as many boxes as fit without adding extra css with mobile query. (@media ...)

Answers 2

You are (probably) a victim of CSS3 100vh not constant in mobile browser assuming that vh chaning is the reason for vmin changing too.

Possible solutions:

  1. use Javascript and manually set the size
  2. use vmax in combination with aspect-ratio media queries to estimate vmin
    (feels hacky but would most likely accomplish what you want)
  3. prevent the address bar from hiding in the first place: https://stackoverflow.com/a/33953987/2422125
  4. prevent the address bar from showing up in the first place: go fullscreen: How to make a <div> always full screen?
  5. try <meta name="viewport" content="width=device-width,height=device-height, initial-scale=1, user-scalable=no">
  6. use grid instead like androbin sugested (probably the best)
Read More

Wednesday, August 16, 2017

Styling error in default browsers of Samsung and Apple, Chrome works fine

Leave a Comment

The mobile page of http://www.ergotopia.de/ergonomie-shop/ergonomische-kissen/orthopaedisches-sitzkissen should look like the right (how it is in inspection of chrome) but on smartphone default browser it looks like left. On Smartphone Chrome browser it looks normal as well, but most people use default browsers unfortunately.

enter image description here

I tried to effect the weird looking class "product-info" with following, but without any change. Do you know whats wrong here?

.product-info {      clear:both;     float:left;     display:block; } 

Or is there any opportunity to try in inspection mode on mobile?

1 Answers

Answers 1

I found a possible way to remotely debug Samsung Internet via Chrome chrome://inspectwith this manual: https://samsunginter.net/docs/remote-debugging

Out of some reason I cannot get it work. I followed the manual but there is no such link like highlighted here: enter image description here

Is it working on your desktop?

I couldnt find a solution to inspect Samsung Internet Browser, but I was able to fix the weird looking problem with giving the boxes a min-width:100% Dont really know why this is now working, but it does

Read More

Tuesday, June 6, 2017

Bootstrap 3 table-responsive not working. X-scrollbar appears on whole site rather than table

Leave a Comment

When my screen width decreases smaller than the minimum width my table is able to display, rather than getting a horizontal scrollbar on the table-responsive wrapper, it is increasing the width of my whole site. I have tried every SO solution I've come across with no luck.

I suspect this has something to do with my flexbox styling. Basically, I've styled my site so that my main page content section (which lives inside <div id="aspnet-placeholder-content" class="container"></div>) will take up the remaining height of the viewport after the footer and sticky header are accounted for. So far I've had no issues, besides this one.

How can I stop the table from expanding the width of my site?

EDIT: Here's a JSFiddle in case you don't like SO's built-in snippet functionality.

$(document).ready(function() {    $("a").on("click", function(e) {      e.preventDefault();    })    $("form").on("submit", function(e) {      e.preventDefault();    })  });
body {    position: absolute;    top: 0;    bottom: 0;    left: 0;    right: 0;  }    form.page-wrapper {    padding: 51px 0 0;    position: static;    height: 100%;    display: flex;    -ms-flex-direction: column;    -webkit-flex-direction: column;    flex-direction: column;  }    section#body-content {    -ms-flex: 1 0 auto;    -webkit-flex: 1 0 auto;    flex: 1 0 auto;    display: flex;    -ms-flex-direction: column;    -webkit-flex-direction: column;    flex-direction: column;  }    section#body-content #subheader {    background: #7e5bbd;    padding-top: 35px;    padding-bottom: 35px;  }    #aspnet-placeholder-content {    flex: 1 0 auto;  }    footer {    background: url("https://s25.postimg.org/4ylsw3w0v/brushed-metal-horizontal-darker-450.jpg") center top;    padding-top: 30px;    padding-bottom: 30px;    margin-top: 20px;  }    @media (min-width: 768px) {    footer .footer-content div:first-child {      text-align: right;      border-right: 1px solid #868686;    }    footer .footer-content div:nth-child(2) {      text-align: left;      border-left: 1px solid #868686;    }  }    footer h5 {    color: #868686;  }    @media (max-width: 767px) {    .padding-left-none-sm,    .padding-right-none-sm {      padding-left: 0;      padding-right: 0;    }  }    @media (min-width: 768px) {    .padding-left-none-sm {      padding-left: 0;    }    .padding-right-none-sm {      padding-right: 0;    }    .text-right-sm {      text-align: right;    }    .text-left-sm {      text-align: left;    }  }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>    <body>    <form class="page-wrapper">      <header class="navbar navbar-inverse navbar-fixed-top">        <div class="container">          <div class="navbar-header">            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">                <span class="icon-bar"></span>                <span class="icon-bar"></span>                <span class="icon-bar"></span>            </button>            <a class="navbar-brand">Logo</a>          </div>          <div class="navbar-collapse collapse">            <ul class="nav navbar-nav navbar-right">              <li id="liHome"><a href="/">Home</a></li>              <li class="dropdown" id="liService">                <a href="/" data-toggle="dropdown" class="dropdown-toggle">Service <i style="font-size:x-small; opacity:0.4;" class="fa fa-chevron-down" aria-hidden="true"></i>                </a>                <ul class="dropdown-menu dropdown-menu-left">                  <li><a href="/">Create Ticket</a></li>                  <li><a href="/">View Tickets</a></li>                </ul>              </li>              <li id="liProposals">                <a href="/">Proposals</a>              </li>              <li id="liProjects">                <a href="/">Projects</a>              </li>              <li id="liDocuments">                <a href="/">Documents</a>              </li>            </ul>          </div>        </div>      </header>      <section id="body-content">        <div id="subheader">          <div class="container">            <div class="col-sm-2 col-sm-push-10 padding-right-none-sm" style="text-align: right;">              <button type="submit" class="btn btn-secondary" id="btnLogout"><strong>Sign out</strong></button>            </div>            <div class="col-sm-5 col-sm-pull-2 padding-left-none-sm">              <div class="button-group">                <select id="ddlLocations" class="form-control">                    <option selected="selected" value="0">(select option)</option>                    <option value="7889">Option 1</option>                    <option value="8736">Option 2</option>                    <option value="10398">Option 3</option>                  </select>              </div>            </div>          </div>        </div>        <div id="aspnet-placeholder-content" class="container">          <!--This is where page-specific server-generated content from ASP.NET will render-->          <h3>Page Title</h3>          <br>          <div style="overflow-x: auto">            <table id="tblLocs" class="table table-striped">              <tbody>                <tr>                  <th>System</th>                  <th>Location Type</th>                  <th>Location</th>                  <th style="text-align: center;">Wired</th>                  <th style="text-align: center;">Equipped</th>                  <th style="text-align: center;">Programmed</th>                  <th style="text-align: center;">Tested</th>                </tr>                <tr>                  <td>Access Control</td>                  <td>Computer Station</td>                  <td>2nd Floor IT Room</td>                  <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                </tr>                <tr>                  <td>&nbsp;</td>                  <td>&nbsp;</td>                  <td>Security Office</td>                  <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                </tr>                <tr>                  <td>&nbsp;</td>                  <td>Badging Station</td>                  <td>Security Desk</td>                  <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                </tr>                <tr>                  <td>&nbsp;</td>                  <td>Panel Location</td>                  <td>1st Floor Comm and Data Room</td>                  <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                </tr>                <tr>                  <td>&nbsp;</td>                  <td>&nbsp;</td>                  <td>IT Closet</td>                  <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                  <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>                </tr>              </tbody>            </table>          </div>        </div>      </section>      <footer>        <div class="container">          <div class="row text-center footer-content">            <div class="col-sm-6">              <h5>Footer text</h5>            </div>            <div class="col-sm-6">              <h5>Copyright stuff</h5>            </div>          </div>        </div>      </footer>    </form>  </body>

4 Answers

Answers 1

Thanks to everyone who offered a solution. All of them seem to involve setting the width of my wrapper to 100%, like this:

#aspnet-placeholder-content {   flex: 1 0 auto;   width: 100%; } 

The problem is, this nullifies the .container bootstrap styling, which sets hard-coded widths in pixels based on viewport size. I don't want full-page width content, so I've added a new class that's like .container, but uses max-width instead of width:

.container-max {   margin-right: auto;   margin-left: auto;   padding-left: 15px;   padding-right: 15px; } @media (min-width: 768px) {   .container-max {     max-width: 750px;   } } @media (min-width: 992px) {   .container-max {     max-width: 970px;   } } @media (min-width: 1200px) {   .container-max {     max-width: 1170px;   } } 

Now my wrapper uses this new class instead of .container, and having width: 100% on the wrapper will have the desired effect.

<div id="aspnet-placeholder-content" class="container-max"> 

Demo of final result

Answers 2

Add flex-wrap: wrap; display: flex; max-width: 100%; to #aspnet-placeholder-content this will wrap your table according to its parent.

#aspnet-placeholder-content {     flex: 1 0 auto;     flex-wrap: wrap;     display: flex;     max-width: 100%; } 

Example

Answers 3

set the width property to 100% ...

a horizontal scrollbar will appear on the table ...

I also moved the h3 tag from the inside of this div ...

 #aspnet-placeholder-content {  flex: 1 0 auto;  width: 100%;   } 

if you want the table to truly be responsive and resize with the page you will have to write some more code regarding individual cells ...

an example of the this can be hound in this thread ...

and another cool solution for a responsive data-table is in this site...

Answers 4

I have changed some css and style and class in your demo and here is the link

<form class="page-wrapper">   <header class="navbar navbar-inverse navbar-fixed-top">     <div class="container">       <div class="navbar-header">         <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">           <span class="icon-bar"></span>           <span class="icon-bar"></span>           <span class="icon-bar"></span>         </button>         <a class=navbar-brand>Logo</a>       </div>       <div class="navbar-collapse collapse">         <ul class="nav navbar-nav navbar-right">           <li id="liHome"><a href="/">Home</a></li>           <li class="dropdown" id="liService">             <a href="/" data-toggle="dropdown" class="dropdown-toggle">                             Service <i style="font-size:x-small; opacity:0.4;" class="fa fa-chevron-down" aria-hidden="true"></i>                         </a>             <ul class="dropdown-menu dropdown-menu-left">               <li><a href="/">Create Ticket</a></li>               <li><a href="/>">View Tickets</a></li>             </ul>           </li>           <li id="liProposals">             <a href="/">                             Proposals                         </a>           </li>           <li id="liProjects">             <a href="/">                             Projects                         </a>           </li>           <li id="liDocuments">             <a href="/">                             Documents                         </a>           </li>         </ul>       </div>     </div>   </header>   <section id="body-content" class="continer">     <div id="subheader">       <div class="container">         <div class="col-sm-2 col-sm-push-10 padding-right-none-sm" style="text-align: right;">           <button type="submit" class="btn btn-secondary" id="btnLogout"><strong>Sign out</strong></button>         </div>         <div class="col-sm-5 col-sm-pull-2 padding-left-none-sm">           <div class="button-group">             <select id="ddlLocations" class="form-control">               <option selected="selected" value="0">(select option)</option>               <option value="7889">Option 1</option>               <option value="8736">Option 2</option>               <option value="10398">Option 3</option>             </select>           </div>         </div>       </div>     </div>     <div id="aspnet-placeholder-content" style="padding:0 15px">       <!--This is where page-specific server-gen"tblLocsted content from ASP.NET will render-->       <h3>Page Title</h3>       <br />       <div class=" table-responsive">         <table id="tblLocs" class="table table-striped">           <tbody>             <tr>               <th>System</th>               <th>Location Type</th>               <th>Location</th>               <th style="text-align: center;">Wired</th>               <th style="text-align: center;">Equipped</th>               <th style="text-align: center;">Programmed</th>               <th style="text-align: center;">Tested</th>             </tr>             <tr>               <td>Access Control</td>               <td>Computer Station</td>               <td>2nd Floor IT Room</td>               <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>             </tr>             <tr>               <td>&nbsp;</td>               <td>&nbsp;</td>               <td>Security Office</td>               <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>             </tr>             <tr>               <td>&nbsp;</td>               <td>Badging Station</td>               <td>Security Desk</td>               <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>             </tr>             <tr>               <td>&nbsp;</td>               <td>Panel Location</td>               <td>1st Floor Comm and Data Room</td>               <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>             </tr>             <tr>               <td>&nbsp;</td>               <td>&nbsp;</td>               <td>IT Closet</td>               <td style="text-align:center;"><i class="fa fa-check-square-o" title="Task complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>               <td style="text-align:center;"><i class="fa fa-square-o" title="Task not yet complete"></i></td>             </tr>           </tbody>         </table>       </div>     </div>   </section>   <footer>     <div class="container">       <div class="row text-center footer-content">         <div class="col-sm-6">           <h5>Footer text</h5>         </div>         <div class="col-sm-6">           <h5>Copyright stuff</h5>         </div>       </div>     </div>   </footer> </form>  $(document).ready(function() {   $("a").on("click", function(e) {     e.preventDefault();   })   $("form").on("submit", function(e) {     e.preventDefault();   }) }); 

DemoLink

body {   position: absolute;   top: 0;   bottom: 0;   left: 0;   right: 0; }  form.page-wrapper {   padding: 51px 0 0;   position: static;   height: 100%;   display: flex;   -ms-flex-direction: column;   -webkit-flex-direction: column;   flex-direction: column; }  section#body-content {   -ms-flex: 1 0 auto;   -webkit-flex: 1 0 auto;   flex: 1 0 auto;   display: flex;   -ms-flex-direction: column;   -webkit-flex-direction: column;   flex-direction: column; }  section#body-content #subheader {   background: #7e5bbd;   padding-top: 35px;   padding-bottom: 35px; }  #aspnet-placeholder-content {   flex: 1 0 auto; }  footer {   background: url("https://s25.postimg.org/4ylsw3w0v/brushed-metal-horizontal-darker-450.jpg") center top;   padding-top: 30px;   padding-bottom: 30px;   margin-top: 20px; }  @media (min-width: 768px) {   footer .footer-content div:first-child {     text-align: right;     border-right: 1px solid #868686;   }   footer .footer-content div:nth-child(2) {     text-align: left;     border-left: 1px solid #868686;   } }  footer h5 {   color: #868686; }  @media (max-width: 767px) {   .padding-left-none-sm,   .padding-right-none-sm {     padding-left: 0;     padding-right: 0;   } }  @media (min-width: 768px) {   .padding-left-none-sm {     padding-left: 0;   }   .padding-right-none-sm {     padding-right: 0;   }   .text-right-sm {     text-align: right;   }   .text-left-sm {     text-align: left;   } } 
Read More

Sunday, October 2, 2016

Soundcloud embedded player on mobile

Leave a Comment

Here is how a SoundCloud embedded player on a HTML page looks like on mobile device:

enter image description here

It's rather annoying, because the user has to click "Listen in browser", and then, often, it doesn't start like it should, and so the user has to click "Pause" button and "Play" again.

How to have the normal look, even on mobile devices? :

enter image description here


Here is example of embedding code:

<iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/271188615&amp;color=ff5500&amp;auto_play=false&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false"></iframe> 

2 Answers

Answers 1

I am going to suggest not using an embedded iframe for the player and instead use SoundCloud's HTTP API

My answer does not focus on any methods to trick the embedded iframe code into not thinking it is mobile. Instead I am showing an alternative path to how to do your own native SoundCloud player.

Doing this guarantees:

  • You have full control over your UI
  • You have full control over playback

I've gone ahead and built a sample application in Android. Assuming you are looking for Android here because of the status bar in the posted question's image.

Also as requested there is a web project, that will work on mobile. The web project is using the SoundCloud api JavaScript wrapper. Oddly there appears to be a bug I am seeing on mobile. I tested on nexus 6P and iPhone 6. Their player they provide doesn't start playing on page load, appears to be some sort of buffering issue. I will update when I know more. The Web player is working but requires pressing play button twice similar to how you described the issue with the embedded player. I will look into the buffering issue when I have more time.

You can find my example project here:

Web Project: https://github.com/davethomas11/stackoverlow_Q_39625513/tree/master/WebPlayer hosted here -> https://www.daveanthonythomas.com/remote/so39625513/

Android: https://github.com/davethomas11/stackoverlow_Q_39625513/SoundCloudPlayer

Check it out, and ask me any questions regarding implementation if anything is not clear. That goes for anyone reading this answer.

The solution is done natively in Java. But it could also be done in HTML and Javascript if that is what you prefer, because we are using their HTTP Rest API the platform does not matter.

Going completely custom, this way gives us full control over the UI. My UI isn't the most beautiful, but it can be as ugly or as beautiful as you want with this level of control ;) ->

SoundCloudPlayer

I will break down the basic steps of using sound cloud's api to accomplish this.

Luckily for us playback is very straight forward. You can skip all of the authentication requirements. As any endpoints you will be using do not require authentication.

All you need is a client id to make your requests. I recommend registering an app with sound cloud, but you can use the embedded player's client id like I did.

Note: the embedded player uses the client id -> cUa40O3Jg3Emvp6Tv4U6ymYYO50NUGpJ

The basis of this implementation is the tracks endpoint: https://developers.soundcloud.com/docs/api/reference#tracks

This endpoint gives us almost everything we need:

  • streaming url
  • title, artist name
  • artwork

But there is one thing missing and that is the waveform data points to display SoundCloud's brand identifying wave form.

The basics of getting this data requires a little bit of hacking. But the data is there in a pure enough form to use.

If you inspect the response of a call to get the embedded player, you'll notice a resource being loaded in the source code by the name of waveform_url. This url returns a nice json document with all the wave point information: https://wis.sndcdn.com/sTEoteC5oW3r_m.json

I've adapted my solution to parse the wave form data from the embedded player, by retrieving it from that url.

You'll notice I've made a very crude version. With a little elbow grease this can be turned into something nice, and even unique. But the basics are there for acquiring it.

enter image description here

Another endpoint I have implemented in my solution is the comments endpoint: https://developers.soundcloud.com/docs/api/reference#comments

I have not yet added it to the UI. But the API code should shed some light onto it's use.

The Android project uses the following libraries:

And for those not familiar, since it is semi new: - Android DataBinding https://developer.android.com/topic/libraries/data-binding/index.html

Please feel free to use my solution as a base, as I've released it under the GNU license. That goes to anyone reading this.

I'd like to consider adding a similar iOS solution to the git-hub repository too as well.

Here is the web project as a snippet:

/*!   * jQuery UI Touch Punch 0.2.3   *   * Copyright 2011–2014, Dave Furfero   * Dual licensed under the MIT or GPL Version 2 licenses.   *   * Depends:   *  jquery.ui.widget.js   *  jquery.ui.mouse.js   */  !function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);    /**   * Created by dave on 16-09-26.   */  function WaveForm(waveformPngUrl) {        var self = this;        var heightRatio;      var waveformUrl = waveformPngUrl.replace(/png$/, "json");      waveformUrl = waveformUrl.replace(/:\/\/w1/,"://wis");        var canvas = $('#SoundCloudPlayer .track_waveform');      var heightPX = canvas.get(0).height;      var data;      var progress = 0;        this.load = function () {            $.get(waveformUrl, function (response) {                heightRatio = heightPX / response.height;              data = response;              canvas.css({ height: "" + heightPX + "px" });              self.draw();          });        };        this.draw = function () {            var ctx = canvas.get(0).getContext("2d");          ctx.clearRect(0, 0, canvas.get(0).width, canvas.get(0).height);            var x = 0;              var lineWidth = data.samples.length / canvas.width();          var progressPoint =  canvas.get(0).width - ((1 - progress) * canvas.get(0).width);            ctx.beginPath();          ctx.lineWidth = lineWidth / 2;          ctx.strokeStyle = "#ff8000";          var progressFound = false;            for (var i = 0; i < data.samples.length; i++) {                if (x > progressPoint && !progressFound) {                  ctx.stroke();                  ctx.closePath();                  ctx.beginPath();                  ctx.strokeStyle = "#000";                  progressFound = true;              }                var ratio = (data.samples[i] * heightRatio) / heightPX;              var drawTo = heightPX - ratio * heightPX;                ctx.moveTo(x, heightPX);              ctx.lineTo(x, drawTo);                x += lineWidth;          }            ctx.stroke();          ctx.closePath();        };        this.setProgress = function (newProgress) {          progress = newProgress;          self.draw();      }  }    var player, mTrack, media, seekBarInterval, waveForm;  var updatingSeekBar = false;    $(function () {        SC.initialize({          client_id: 'cUa40O3Jg3Emvp6Tv4U6ymYYO50NUGpJ'      });        player = document.getElementById("SoundCloudPlayer");        checkQueryURLForTrackId();      loadTrackEnteredInInput();        $("form button").button();  });    function loadTrackEnteredInInput() {        loadTrack(getTrackId());  }    function loadTrack(trackId) {        SC.get('/tracks/' + trackId).then(function (track) {            // Inspect for info on track you want:          console.log(track);          mTrack = track;            renderTrack(track);          streamTrack(track);            waveForm = new WaveForm(track.waveform_url);          waveForm.load();        }, function () {            alert("Sorry no track found for track id: "+ trackId)      });  }    function renderTrack(track) {        $(player).find(".track_artist").text(track.user.permalink);      $(player).find(".track_title").text(track.title);      $(player).find(".track_artwork").attr('src', track.artwork_url);      $(player).find(".track_seek_bar").slider(          {              orientation: "horizontal",              range: "min",              max: track.duration,              value: 0,              change: seek          });    }    function streamTrack(track) {        SC.stream('/tracks/' + track.id).then(function (mediaPlayer) {          media = mediaPlayer;            console.log(media);            play();      });  }    function play() {      if (!media) {          return;      }        $(player).find(".track_play").hide();      $(player).find(".track_pause").fadeIn();        media.play();        seekBarInterval = setInterval(updateSeekBar, 500);  }    function pause() {      if (!media) {          return;      }        $(player).find(".track_pause").hide();      $(player).find(".track_play").fadeIn();      media.pause();        clearInterval(seekBarInterval);  }    function seek() {      if (!media) {          return;      }        if (!updatingSeekBar) {          media.seek($(player).find(".track_seek_bar").slider("value"));      }  }    function updateSeekBar() {      if (!media) {          return;      }        waveForm.setProgress(media.currentTime() / mTrack.duration);        updatingSeekBar = true;      $(player).find(".track_seek_bar").slider("value", media.currentTime());      updatingSeekBar = false;  }    /**   * Loads a different track id based on   * url query   */  function checkQueryURLForTrackId() {      var query = getUrlVars();      if (query.trackId) {          $('[name=trackId]').val(query.trackId);      }  }    //http://stackoverflow.com/questions/4656843/jquery-get-querystring-from-url  // Read a page's GET URL variables and return them as an associative array.  function getUrlVars()  {      var vars = {}, hash;      var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');      for(var i = 0; i < hashes.length; i++)      {          hash = hashes[i].split('=');          vars[hash[0]] = hash[1];      }      return vars;  }    function getTrackId() {      return trackId = $('[name=trackId]').val();  }
body {      font-family: 'Raleway', sans-serif;  }    #SoundCloudPlayer .track_artwork {      float:left;      margin-right: 6px;  }    #SoundCloudPlayer .track_artist {      font-size: small;      margin-bottom: 4px;  }    #SoundCloudPlayer .track_title {      margin-top: 0px;      font-weight: bold;  }    #SoundCloudPlayer .track_control {      cursor: pointer;      display: none;  }    #SoundCloudPlayer .track_seek_bar .ui-slider-range { background: orange; }  #SoundCloudPlayer .track_seek_bar .ui-slider-handle { border-color: orange; }    #SoundCloudPlayer .track_waveform {      width: 100%;  }
<html>  <head>      <meta name="viewport" content="initial-scale=1, maximum-scale=1">      <title>SoundCloud API Web Player Demo</title>      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>      <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.0/themes/smoothness/jquery-ui.css" />      <script src="jquery.ui.touch-punch.min.js"></script>      <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.0/jquery-ui.min.js"></script>      <script src="https://connect.soundcloud.com/sdk/sdk-3.1.2.js"></script>      <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet" />      <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />  </head>  <body>    <form method="get">      <label for="trackId">Load Track:</label>      <input name="trackId" type="text" value="271188615" />      <button>GO</button>  </form>    <section id="SoundCloudPlayer">        <img class="track_artwork" />      <p class="track_artist"></p>      <p class="track_title"></p>      <i class="material-icons track_play track_control" onClick="play()">play_circle_filled</i>      <i class="material-icons track_pause track_control" onClick="pause()">pause_circle_filled</i>      <canvas class="track_waveform"></canvas>      <div class="track_seek_bar" ></div>  </section>  </body>  </html>

Answers 2

Mini Player (height=20) has similar look & feel for desktops and mobiles.

<iframe width="100%" height="20" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/271188615&color=ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false"></iframe> 
Read More

Tuesday, August 23, 2016

meta name=“viewport” is ignored by browser(?)

Leave a Comment

previously in <HEAD> it was

<meta name="viewport" content="width=device-width, initial-scale=1.0"/> 

As you can see issue in screenShots that I have attached below.. there was issue of UI break so then I have updated <HEAD> with following code

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width; initial-scale=0.9; maximum-scale=0.9; minimum-scale=0.9;" /> 

But Still issue is there

Web page works well with resolution of 1280 X 800 as you can look at this image

enter image description here

these 3 columns (with black vertical line separated) are the <td> inside that a container with fixed width in px, and I cant change it to % due to some limitations. only main container have width : 100%, (Main container: with full page width behind all page content-with white BG)

I have attached screen shots of issues with screen resolution

On 1024 X 768

enter image description here

As you can see On browser with ratio 1024 X 768 "mobile image" is going beyond White box(Main container)

on 1920 X 1080

enter image description here

Here browser ratio is 1920 X 1080 and main container (White box) is 100% of width but those three columns (<TD>) are not, all three width remains same as previous images and main container is 100%

Update: Code link https://jsfiddle.net/p6x6jsgt/3/

5 Answers

Answers 1

The problem is not your meta viewport tag. After having read all the comments here are a couple solutions to your problem:

A non-optimal solution:

Keep the table layout, change to percentage widths and use text blocks with white-space:nowrap; and <br> hard-coded line breaks with different font sizes depending on device screen size.

- About the layout:

Your .preview-panel has a fixed width in rem. To solve this, make the following changes:

.preview-panel {     background-size:100% auto;     width:100%; } 

Now you will notice layout issues with the other td. That's because you have to set them to percentage widths, for example:

.template-editor {     width:100%; } .template-editor td {     width:33%; } 

- About the text blocks:

You said setting widths to percentages would mess up your text blocks. Well, unfortunately there's no magical solution for this and all you can do about it (with your current layout) is to add this to whatever text block you put in there:

.foo {     white-space:nowrap; } 

You would also have to fix your line breaks with <br> like so:

Lorem ipsum dolor sit amet,<br> consectetur adipiscing elit.<br> Fusce pulvinar aliquet luctus. 

You could make the line breaks responsive if you wanted to, with something like (HTML):

<span class="line-break"></span> 

(CSS):

.line-break {     display:block; } 

Then you'd have the opportunity to set different font sizes on your media queries, and you could also hide the purposeful line-breaks with display:none;. This is, in my opinion, a better solution than plain old <br>.

With this, your layout should look better in all devices. That being said, this is still a poor solution and an entirely different approach is necessary, in my opinion.

A better solution:

Use flex or maybe just floated items, but not a table when your layout essentially is not a table. You have three panels, why would you forcefully use a table layout for that? Here's an example with flex:

.container {    display:flex;    align-items:stretch;    justify-content:center;  }  .container__panel {    flex-grow:1;    height:600px;    border:1px solid black;  }
<div class="container">    <div class="container__panel"></div>    <div class="container__panel"></div>    <div class="container__panel"></div>  </div>

Disclaimer: the weird container__panel is BEM notation: http://getbem.com/introduction/

Answers 2

Add

td{     width: 33%; } 

For dividing the columns equally ,

Remove width css from the below class so that it can adjust width according to parent class (i have commented the code which i have removed from css)

  #cardListHolder {         padding-top: 0.4375rem;         /*width: 21.5625rem;*/     }   .edit-card .inner {         margin: auto;         padding: 0 2.1875rem;     /*  width: 18.75rem;*/     } .preview-panel {         background: rgba(0, 0, 0, 0) url("http://cdnsq.ur-nl.com/assets/mobile-898fc89b167945138c3d9f551a5ce551.png") no-repeat scroll center 0;         height: 26.25rem;         margin: auto;         padding: 3.4375rem 0.8125rem 0;      /* width: 13.3125rem;*/     } 

Just try replacing this whole css with your css. I hope this will fix your issue.

    *,     *::before,     *::after {         box-sizing: border-box;     }      ul {         list-style: outside none none;         margin: 0;     }      .sectional-content {         background: #f6f6f6;         color: #222;         cursor: auto;         font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;         font-style: normal;         font-weight: normal;         line-height: 1.5;         margin: 0;         padding: 0;         position: relative;     }      .wrapper {         min-height: 100%;         position: relative;     }      .centered-container {         margin-left: auto;         margin-right: auto;         width: 96.6667%;         padding-left: 0.3125rem;         padding-right: 0.3125rem;         position: relative;     }      .tabs-content {         background: #fff none repeat scroll 0 0;         border: 1px solid red;         margin-top: -1px;         padding: 1.5625rem;         margin-bottom: 0;         width: 100%;     }      .divider1 {         height: 18px;     }      .template-editor {         background: #fff none repeat scroll 0 0;         border: 0 none;         margin-bottom: 1.25rem;         table-layout: auto;     }      .template-editor tr {         background: transparent none repeat scroll 0 0 !important;     }      td{         width: 33%;     }      .add-remove-template,     .edit-card {         padding-top: 5px !important;         vertical-align: top;     }      .add-remove-template {         border-left: 0 none;         padding-left: 0 !important;         padding-right: 0 !important;         vertical-align: top;     }      table tr th,     table tr td {         color: #222;         font-size: 0.875rem;         padding: 0.5625rem 0.625rem;         text-align: left;     }      #cardListHolder {         padding-top: 0.4375rem;     }      .preview-template,     .edit-card {         border-left: 2px solid #808285;         padding: 0 1.875rem !important;         vertical-align: top;     }      .edit-card .inner {         margin: auto;         padding: 0 2.1875rem;     }      .preview-panel {         background: rgba(0, 0, 0, 0) url("http://cdnsq.ur-nl.com/assets/mobile-898fc89b167945138c3d9f551a5ce551.png") no-repeat scroll center 0;         height: 26.25rem;         margin: auto;         padding: 3.4375rem 0.8125rem 0;     } 

Answers 3

I think you want something like this it fits it self in every resolution.

.section {    box-sizing: border-box;    padding: 0 16px;    width: 33%;    float: left;  }  .scroll-container {    height: 360px;    overflow-y: auto;    border-right: 1px solid black;  }  .edit-card {    height: 360px;    border-right: 1px solid black;  }  .preview-panel img {    width: 100%;    max-width: 250px;  }
<div class="content">    <div class="section scroll-container" style="height: 360px">      <ul id="cardListHolder">        <li></li>      </ul>    </div>    <div class="section edit-card">      <p>      edit something      </p>    </div>    <div class="section preview-panel">      <img src="http://cdnsq.ur-nl.com/assets/mobile-898fc89b167945138c3d9f551a5ce551.png"/>    </div>  </div>

Answers 4

May be over-looking here... Have you tried using media queries to resolve this? See if this link is any good. https://developers.google.com/web/fundamentals/design-and-ui/responsive/fundamentals/use-media-queries?hl=en

Of course it would mean alot more coding to get it to work fluently and changes will need to be done.

And have you also used the text-align: center; attribute in your css for the text paragraphs in your columns,rather than "setting it perfectly" to align correctly on all three columns followed of course by removing/setting the white space.

From what i can see, i think this may solve your answer.

Answers 5

Remove the defined width you have given in

#cardListHolder { padding-top: 0.4375rem; width: 21.5625rem; 

}

and in

.edit-card .inner { margin: auto; padding: 0 2.1875rem; width: 18.75rem; 

}

and use

th,td{ width: 33%; 

}

<!doctype html>  <html>  <head>  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>  <style>  	*, *::before, *::after {      box-sizing: border-box;  }  ul {      list-style: outside none none;      margin: 0;  }  .sectional-content{        background: #f6f6f6;      color: #222;      cursor: auto;      font-family: "Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;      font-style: normal;      font-weight: normal;      line-height: 1.5;      margin: 0;      padding: 0;      position: relative;    }  .wrapper {      min-height: 100%;      position: relative;  }  .centered-container{     margin-left: auto;      margin-right: auto;  width: 96.6667%;  padding-left: 0.3125rem;      padding-right: 0.3125rem;      position: relative;  }  .tabs-content {      background: #fff none repeat scroll 0 0;      border: 1px solid red;      margin-top: -1px;      padding: 1.5625rem;       margin-bottom: 0;      width: 100%;  }  .divider1{    height: 18px;  }   .template-editor {      background: #fff none repeat scroll 0 0;      border: 0 none;      margin-bottom: 1.25rem;      table-layout: auto;  }  .template-editor tr {      background: transparent none repeat scroll 0 0 !important;      position:relative;  }  .add-remove-template, .edit-card {      padding-top: 5px !important;      vertical-align: top;  }  .add-remove-template {      border-left: 0 none;      padding-left: 0 !important;      padding-right: 0 !important;      vertical-align: top;  }  table tr th, table tr td {      color: #222;      font-size: 0.875rem;      padding: 0.5625rem 0.625rem;      text-align: left;  }  #cardListHolder {      padding-top: 0.4375rem;        }  .preview-template, .edit-card {      border-left: 2px solid #808285;      padding: 0 1.875rem !important;      vertical-align: top;  }  .edit-card .inner {      margin: auto;      padding: 0 2.1875rem;        }  .preview-panel {      background: rgba(0, 0, 0, 0) url("http://cdnsq.ur-nl.com/assets/mobile-898fc89b167945138c3d9f551a5ce551.png") no-repeat scroll center 0;        height: 26.25rem;      margin: auto;      padding: 3.4375rem 0.8125rem 0;      width: 13.3125rem;  }    th,td{  	width: 33%;  }  </style>  </head>  <body>  <div class="sectional-content">     <div class="wrapper">        <div class="centered-container">            <div class="tabs-content">              <div class="divider1"></div>                <table class="template-editor" cellpadding="0" cellspacing="0">                  <tbody>                  <tr>                    <td class="add-remove-template">                      <div class="scroll-container" style="height: 360px">                        <ul id="cardListHolder">                          <li></li>                        </ul>                      </div>                    </td>                    <td class="edit-card">                      <div class="inner">                                              </div>                    </td>                    <td class="preview-template">                      <div class="preview-panel">                                             </div>                    </td>                  </tr>                </tbody>              </table>              </div>          </div>        </div>     </div>     </body>     </html>

Read More

Friday, June 24, 2016

Horizontally and vertically centered iframe with aspect ratio 16:9 that uses as much screen estate as possible without being cropped anywhere

Leave a Comment

Requirements:

  • The HTML: The iframe HAS to be inside of a containing div. See code down below.
  • The CSS: The container should be able to have ANY valid width and height using the vw and vh viewport units. Se code down below.
  • Yes, the width and height HAS to be in vw and vh.
  • The static video preview image should NEVER be cropped.
  • The static video preview image should NOT have any black bars above and below (letterboxing).
  • The static video preview image should NOT have any black bars to the left or to the right (pillarboxing).
  • The static video preview image should use as much space estate as possible inside the div that contains it.
  • The static video preview image should ALWAYS keep its aspect ratio of 16:9.
  • Scrollbars should NEVER appear.
  • The static video preview image should be centered vertically as well as horizontally inside the div that contains it.
  • Responsive Web Design.

When resizing the browser or viewport all of the above requirements should be fulfilled.

HTML:

<div class="container">    <iframe></iframe> </div> 

CSS:

.container {    width:90vw;    height:50vh; } 

7 Answers

Answers 1

.container {     width:90vw;     height:50vh; } .container iframe {     width: 100%;     height: 100%; } 

Seems to work quite nicely in this fiddle https://jsfiddle.net/1q10L7hj/

Answers 2

if you want Responsive use

.container, iframe {   width:100%;   height:auto; } 

Answers 3

Same solution, but no extra markup for keeping the ratio.

JsFiddle with same comments totally not needed.

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"> <title>Fully Container Centred Iframe</title> <meta name="generator" content="PSPad editor, www.pspad.com"> <style> .container {     display:table-cell; /* (specs: omitted table parts, the browser will insert mandatory elements in the dom tree) */     position:relative;     padding:; /* optional, margins ignored */     width:100vw; /* any value */     height:1vh; /* will expand by the :before element */     overflow:hidden; /* hide eventual black bars */     background:tan; /* bg-colors just for demo testing */     vertical-align:middle;     text-align:center; } .container:before {     display:block;     padding-top:56%; /* keeps the 16/9 ratio for the AP */     height:0;     background:red;     content:"\a0"; } .container iframe {     position:absolute; /* to be ratio consistent */     top:-.5%;     left:-.5%; /* overflow eventual black bars */     border:0;     width:101%; /* grow some to avoid thinner black bars */     height:101%;     overflow:hidden; /* for html5 browsers the html attribute is depreciated */     background:gold;     vertical-align:middle; /* remove the textline's descendent space */ } </style> </head><body>  <div class="container">     <iframe scrolling="no" src=""></iframe> </div>  </body></html> 

Answers 4

I have gotten the result you wanted, I however had to add an extra div as the parent of the .container class. This JSFiddle should work for users on chrome (Windows desktop version) however when I tried to use the same fiddle on Edge and IE11 I found that it would create the undesired letter-box effect due to the image cover zooming too far out.

HTML

<div id="wrapper">   <div class="container">       <iframe scroll="no" src="https://www.youtube.com/embed/YL9RetC0ook" frameborder="0" allowfullscreen>       </iframe>   </div> </div> 

CSS

body {   margin: 0; }  #wrapper {   width: 90vw;   height: 50vh; }  .container,iframe {   width: 100%;   height: 100%; } 

I am not sure if this works for Firefox, so perhaps if you have Firefox you can try it on my JSFiddle. However for Chrome (at the very least) this should be the solution you where looking for as stated by the requirements you listed.

Answers 5

why don't you just use the calc method to get the aspect ratio width you are wanting?

HTML

<div class="container">     <iframe src="" frameborder="0"></iframe> </div> 

SCSS

<style>  $width = 80vw;  .container {     width: $width;     height: calc(($width/16) * 9);     position: relative; } iframe {     position: absolute;     width: 100%;     height: 100%;     top: 50%;     left: 50%;     -webkit-transform: translate(+50%, -50%);     transform: translate(+50%, -50%); }  </style> 

then you can change the width of it anywhere and apply whatever positioning you want on the container div and the iframe with follow suit

Answers 6

I think the table-cell display could solve this. Just apply it on the container so the iframe is the content

According to specs the browser will insert dummy elements where it needs to render the cell correctly and fully centre and to contain its content and if it need, grow with it.

The requirements: I think some of them is beyond the scope of your question, they will also depend on what is loaded in the iframe, out of control of this container document. My suggested code is simple, but I believe it meets all requirements possible for the iframe parent and still be crossbrowser friendly.

The forbidden black bars and the mandatory aspect ratio could still be at fault in the loaded document. If you can't control whats loaded, the last option might be the "srcdoc" and "seamless" attributes, but that would exclude e.g. all IE versions.

JsFiddle with some comments totally not needed. Hope the edit below solves the case.

Anyway, I had fun! Thanks! :)

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"> <title>Fully Container Centred Iframe</title> <meta name="generator" content="PSPad editor, www.pspad.com"> <style> .container {     display:table-cell;     padding:;     width:100vw;     height:20vh;     background:tan;     vertical-align:middle;     text-align:center; } .container .ratio{     display:inline-block;     position:relative;     padding-bottom:56%;     width:100%;     height:0;     overflow:hidden;     vertical-align:middle; } .container iframe {     position:absolute;     top:-1%;     left:-1%;     border:0;     width:102%;     height:102%;     overflow:hidden;     vertical-align:middle; } </style> </head><body>  <div class="container">     <div class="ratio">         <iframe scrolling="no" src=""></iframe>     </div> </div>  </body></html> 

Answers 7

I would recommend using a JavaScript window.resize listener to solve this kind of an issue.

Read More