Search code examples
htmlcssresponsive-designmedia-queries

responsive text+images in one line irrespective of the screen display size


I want to align text and banners in one line irrespective of the screen size. Please check the fiddle given below.
If I resize the result window and make it maximum big horizontally, the text and banners are in one line, like I want it.
But when I shrink the result window and make it small, I still need text and banners in one line, which is not happening.

On a desktop monitor I see text + all 3 banners in one line and I want the same display on mobile device, where all 3 banners should shrink with same height.
(The width of all three banners are different but all heights are the same: 60px.)

fiddle: http://jsfiddle.net/moudzdj5/3/

<div id="tophead">
    <div id="mainhead">
        some text
    </div>

    <div id="banners">
        <img src="http://www.bingobugle.com/images/ex234x60.gif">
        <img src="http://www.chilefoundry.com/wp-content/uploads/468x60banner.jpg">
        <img src="http://www.crossingstv.com/wp-content/uploads/2012/07/120x60.png">
    </div>
</div>

Solution

  • CSS Solution:

    I found a CSS solution, provided that you know the width of all banners.

    #tophead {
      width: 100%;
    }
    
    #mainhead {
      width: 15%;
    }
    
    #ads {
      position: absolute;
      top: 15px;
      right: 0px;
      width: 80%;
    }
    #ads img {height:auto;}
    #ads img#ad1 {width: calc(95% * (234/1170));} /*(adWidth / totalSumWidth)*/
    #ads img#ad2 {width: calc(95% * (468/1170));} /*(adWidth / totalSumWidth)*/
    #ads img#ad3 {width: calc(95% * (468/1170));} /*(adWidth / totalSumWidth)*/
    <div id="tophead">
      <div id="mainhead">
        some text
      </div>
    
      <div id="ads">
        <img id="ad1" src="http://www.bingobugle.com/images/ex234x60.gif" />
        <img id="ad2" src="http://www.chilefoundry.com/wp-content/uploads/468x60banner.jpg" />
        <img id="ad3" src="http://www.chilefoundry.com/wp-content/uploads/468x60banner.jpg" />
      </div>
    </div>
    (fiddle: http://jsfiddle.net/nw4f7uh7/)

    This uses CSS' calc() to calculate the width of the banners, a CSS feature I didn't even know existed until yesterday:)

    #ads img#ad1 {width: calc(95% * (234/1170));}
    
    • Between the calc(...) you can perform simple calculations using +, -, * and /, where you can mix units like %, px, em, etc.
    • The above line makes the with of the banner 95% of its parent's total width, multiplied by (234/1170) (its_own_width / total_width_of_all_banners). So basically, it's percentage of the total combined width. This is why you need to know the exact width of all involved banners, for this to work.
    • You need to give all the banners a unique ID in the HTML, because they will all need their own CSS-width-rule (#ad1, #ad2, #ad3).
    • I used 95%. In theory this could be 100%, but there is some space/margin between the banners that I can't find the origin of, causing the last banner to get pushed to the next line. With 98% they already line up next to eachother, but when you make the window smaller, the last one gets pushed again. 95% seems a safe bet.
    • If you don't like the space/margin between the last banner and the right window side that this creates, you can add float:right; to the #ads img{} block. But beware that the banners are mirrored now; the left banner is on the right. So you should flip that around in your HTML as well.
    • This will not work on IE8 and below, and there is almost no support on mobile platforms.

    JS Solution:

    If you want it to work without knowing the exact width of every banner, you need JavaScript.

    (Also, the CSS solution seems to have multi-platform issues, like on mobile browsers... The JavaScript solution should be more consistent.)

    window.onload = resize;
    window.onresize = resize;
    
    function resize() {
      //get a nodeList of all banners
      var banners = document.getElementsByClassName("banner");
      //store total width of all banners together
      var totalBannerWidth = 0;
      for (var i=0; i<banners.length; i++) {
        totalBannerWidth += banners[i].naturalWidth;
      }
      //set new width of each banner
      var containerWidth = document.getElementById("ads").offsetWidth;
      for (var j=0; j<banners.length; j++) {
        banners[j].style.width = 0.95*containerWidth * (banners[j].naturalWidth/totalBannerWidth) +"px";
      }
    }
    #tophead {width: 100%;}
    #mainhead {width: 15%;}
    
    #ads {
      width: 80%;
      position: absolute;
      top: 15px;
      right: 0px;
    }
    #ads img {width:auto; height:auto;}
    <div id="tophead">
      <div id="mainhead">some text</div>
    
      <div id="ads">
        <img class="banner" src="http://www.bingobugle.com/images/ex234x60.gif" />
        <img class="banner" src="http://www.chilefoundry.com/wp-content/uploads/468x60banner.jpg" />
        <img class="banner" src="http://www.chilefoundry.com/wp-content/uploads/468x60banner.jpg" />
      </div>
    </div>
    fiddle: http://jsfiddle.net/nw4f7uh7/2/

    • The JavaScript code performs the same calculation as the CSS' calc(), except it dynamically retrieves the original widths of all banners, and uses those values to scale the banners. This way, you don't have to type in the widths manually, like in CSS.
    • Now there are no individual ID's for each banner, only a shared classname.
    • This is pure JavaScript, no jQuery. But this version will not work on IE8 and below. For better cross-browser compatibility, translate the code to jQuery.