Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scale div with its content to fit window

Tags:

html

jquery

css

I have a fixed-size <div> with some complex content (including text and background images). This <div> has its size hardcoded in pixels (and its content depends on this size, and content positions are hardcoded in pixels as well).

Here is a greatly simplified example: http://jsfiddle.net/dg3kj/.

I need to scale that div and the content inside it, maintaining its aspect ratio, so it fits the window.

A solution that would not require me to manually change <div> contents is preferable (it is generated dynamically and is a bunch of very messy legacy code which I would like to avoid touching). JavaScript (jQuery) solutions are OK (including ones that change the generated content — as long as it is done post-factum of generation itself).

I tried to play with transform: scale(), but it did not yield satisfactory results. See here: http://jsfiddle.net/sJkLn/1/. (I expect the red background to be not visible — i.e. outermost <div> size should not be stretched by the original dimensions of scaled down <div>.)

Any clues?

like image 463
Alexander Gladysh Avatar asked Sep 11 '13 20:09

Alexander Gladysh


People also ask

How do I make a div fit to content?

Answer: Use the CSS display Property You can simply use the CSS display property with the value inline-block to make a <div> not larger than its contents (i.e. only expand to as wide as its contents).

How do you scale a div?

To scale the contents of a div by a percentage with CSS, we can set the zoom and -moz-transform CSS properties. to scale the contents of the element with ID myContainer by a factor of 0.5 by setting zoom to 0.5 and -moz-transform to scale(0.5) .

What is scale () in CSS?

The scale() CSS function defines a transformation that resizes an element on the 2D plane. Because the amount of scaling is defined by a vector, it can resize the horizontal and vertical dimensions at different scales. Its result is a <transform-function> data type.

What does transform scale do?

The transform CSS property lets you rotate, scale, skew, or translate an element. It modifies the coordinate space of the CSS visual formatting model.


4 Answers

let outer = document.getElementById('outer'),         wrapper = document.getElementById('wrap'),         maxWidth  = outer.clientWidth,         maxHeight = outer.clientHeight; window.addEventListener("resize", resize); resize(); function resize(){let scale,     width = window.innerWidth,   height = window.innerHeight,   isMax = width >= maxWidth && height >= maxHeight;      scale = Math.min(width/maxWidth, height/maxHeight);     outer.style.transform = isMax?'':'scale(' + scale + ')';     wrapper.style.width = isMax?'':maxWidth * scale;     wrapper.style.height = isMax?'':maxHeight * scale; }
body {   font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";   background: #e6e9f0;   margin: 10px 0; }   #wrap {   position: relative;   width: 640px;   height: 480px;   margin: 0 auto; } #outer {   position: relative;   width: 640px;   height: 280px;   background: url('https://source.unsplash.com/random') no-repeat center center;   transform-origin: 0% 50%;   border-radius: 10px;   box-shadow: 0px 3px 25px rgba(0, 0, 0, 0.2);   overflow: hidden; } #outer:before {   content: "";   position: absolute;   bottom: 0;   width: 100%;   height: 100px;   -webkit-backdrop-filter: blur(20px);   backdrop-filter: blur(20px); }  #profile {   background: url('https://source.unsplash.com/random/300x300') no-repeat center center;   position: absolute;   width: 60px;   height: 60px;   bottom: 0;   margin: 20px;   border-radius: 100px;   background-size: contain; } #content {   font-size: 20px;   position: absolute;   left: 0px;   bottom: 0;   margin: 30px 100px;   color: white;   text-shadow: 0 1px 2px rgba(0,0,0,0.5); }  #content div:last-child {   font-size: 15px;   opacity: 0.7; }
<div id="wrap"> <div id="outer">   <div id="profile"></div>   <div id="content">     <div>Monwell Partee</div>     <div>UX / UI Designer</div>   </div> </div> </div>
like image 146
dc5 Avatar answered Oct 04 '22 05:10

dc5


I took the answer from dc5, and put it in a small function that allows you to set the scale based on window.

function scaleBasedOnWindow(elm, scale=1, fit=false){     if(!fit){         elm.style.transform='scale('+scale/Math.min(elm.clientWidth/window.innerWidth,elm.clientHeight/window.innerHeight)+')';     }else{         elm.style.transform='scale('+scale/Math.max(elm.clientWidth/window.innerWidth,elm.clientHeight/window.innerHeight)+')';     } } 

if you want the element to fit, and not get cut off, just change Math.min to Math.max, or just set the fit parameter of this function to true.

Minified Version:

function scaleBasedOnWindow(elm,scale=1,fit){if(!fit){elm.style.transform='scale('+scale/Math.min(elm.clientWidth/window.innerWidth,elm.clientHeight/window.innerHeight)+')';}else{elm.style.transform='scale('+scale/Math.max(elm.clientWidth/window.innerWidth,elm.clientHeight/window.innerHeight)+')';}} 
like image 25
SwiftNinjaPro Avatar answered Oct 04 '22 06:10

SwiftNinjaPro


In case anyone building an full-screen application of let's say 1920x1080 and wants to perfectly fit in a smaller screen - e.g 1366x768. This is what I did in Vue.js - but can be done with pure js and css - based on answer above - the main importance is that I set the original width and height specifically otherwise it wasn't working for me:

App.vue (conditional class if lowres exists in localStorage)

    <template>
        <div id="external-app-wrapper" :class="{lowres: isLowRes}">
            <div id="internal-app-wrapper">
                <router-view />
            </div>
        </div>
   </template>
computed: {

      isLowRes() {
         return localStorage.getItem('lowres') !== null
      }
}

scale is calculated as: 1366/1920 and 786/1080

    #external-app-wrapper {
        width: 1920px;
        height: 1080px;
    }

    .lowres #internal-app-wrapper {
        transform-origin: top left;
        transform: scale(0.71145833333, 0.71111111111);
    }

router.js (resolution is optional)

       {
            path: '/app/:resolution?',
            name: 'App Home',
            component: () => import('@/components/routes/HomeRoute'),
            meta: {
                title: 'App Home'
            }
        }

in HomeRoute.vue I have:

        mounted() {
            if (this.$route.params.resolution === 'lowres') {
                localStorage.setItem('lowres', 'true')
                this.$router.push({ path: '/app' })
                this.$router.go()
            } else if (this.$route.params.resolution === 'highres') {
                localStorage.removeItem('lowres')
                this.$router.push({ path: '/app' })
                this.$router.go()
            }
        }

so navigating to /app/lowres redirects to /app and shrinks the whole application and redirecting to /app/highres redirects to /app and resolution is back to normal

Hope someone finds it useful :)

like image 37
Michail Michailidis Avatar answered Oct 04 '22 07:10

Michail Michailidis


Pure JS Based on dc5's answer;
Scales based on window resize

let outer = document.getElementById('outer'),
        wrapper = document.getElementById('wrap'),
        maxWidth  = outer.clientWidth,
        maxHeight = outer.clientHeight;
window.addEventListener("resize", resize);
resize();
function resize(){let scale,
    width = window.innerWidth,
  height = window.innerHeight,
  isMax = width >= maxWidth && height >= maxHeight;

    scale = Math.min(width/maxWidth, height/maxHeight);
    outer.style.transform = isMax?'':'scale(' + scale + ')';
    wrapper.style.width = isMax?'':maxWidth * scale;
    wrapper.style.height = isMax?'':maxHeight * scale;
}
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  background: #e6e9f0;
  margin: 0;
  padding: 0;
}


#wrap {
  position: relative;
  width: 640px;
  height: 480px;
  margin: 0 auto;
}
#outer {
  position: relative;
  width: 640px;
  height: 280px;
  background: url('https://source.unsplash.com/random') no-repeat center center;
  transform-origin: 0% 50%;
  border-radius: 10px;
  box-shadow: 0px 3px 25px rgba(0, 0, 0, 0.2);
  overflow: hidden;
  margin-top: 10px;
}
#outer:before {
  content: "";
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 100px;
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
}

#profile {
  background: url('https://source.unsplash.com/random/300x300') no-repeat center center;
  position: absolute;
  width: 60px;
  height: 60px;
  bottom: 0;
  margin: 20px;
  border-radius: 100px;
  background-size: contain;
}
#content {
  font-size: 20px;
  position: absolute;
  left: 0px;
  bottom: 0;
  margin: 30px 100px;
  color: white;
  text-shadow: 0 1px 2px rgba(0,0,0,0.5);
}

#content div:last-child {
  font-size: 15px;
  opacity: 0.7;
}
<div id="wrap">
<div id="outer">
  <div id="profile"></div>
  <div id="content">
    <div>Monwell Partee</div>
    <div>UX / UI Designer</div>
  </div>
</div>
</div>
like image 33
Monwell Partee Avatar answered Oct 04 '22 05:10

Monwell Partee