Javascript: Retrieve actual, meaningful size (pixels) attributes of flexbox (or any browser-based) items

32 views Asked by At

This is a spinoff from this question, where I was looking for help with aligning flexbox items. I am now trying to use JavaScript to set the font size perfectly so that these elements fill their respective areas (actually 95%, but let's ignore that detail for now) without overflowing their bounds. This gives a rough idea (at least conceptually) of the desired look:

    ___    __   _  _   ___
   / _ \  / / _| || | / _ \
  | | | |/ /_(_) || || (_) |
  | | | | '_ \ |__   _> _ <
  | |_| | (_) |   | || (_) |
   \___/ \___(_)  |_| \___/           07:00  53F
                                      08:00  53F
                                      09:00  54F
 _____ __ ______    __ __  _____      10:00  55F
| ____/_ |  ____|  /_ /_ |/ ____|       etc...
| |__  | | |__      | || | |
|___ \ | |  __|     | || | |
 ___) || | |        | || | |____
|____/ |_|_|        |_||_|\_____|

        PTC  49F  10C

The areas you see here (details availble in the original question) are organized like this (showing the ids here:

[unnamed]
    [time_temp_container]      [right_side]
       [time]                     [icon]
       [temp]                     [forecast00]
                                  [forecast01]
                                    (etc)

From javascript, I can get the elements time_temp_container and time and temp, etc, but I do not find an attribute that shows me the available size of these attributes. I can access the "used" size by referencing, say, time.offsetWidth. And I can see that this value changes as I change the value of time.style.fontSize. But my target width (the number of pixels available) is a value that eludes me. I see screen and all of its attributes (notably screen.width and screen.height). But these values are virtual, not pixels, and besides, I don't see a way to use those to get to (for example) time's width. Then there's window.innerWidth and window.innerHeight, which at least seem to be pixel-based, but again I don't see a relationship I can draw from to get the desired values.

How can I determine the amount of space that is available so that I can detect the font size that will cause current content to fill it?

EDIT

This is a very-trimmed-down version of what I am trying to accomplish, hopefully containing enough of the final code to show the problem. There are two files. The multiclock-sample.js file is referened by name in the multiclock-sample.html file.

multiclock.js

"use strict" ;

var tempsTableElem = document.getElementById('temps') ;
var timeElem = document.getElementById("clocktext") ;
var tempElem = document.getElementById("temptext") ;
var clockElem = document.getElementById("clockDiv") ;
var rightSide = document.getElementById('rightSideContainer') ;
var page = document.getElementById('page') ;
var targetWidth = 0.98 ; // Proportion of full screen width
var startFontSize = 8 ; 
var timeFontSize = 10 ;
var tempFontSize = 10 ;

function updateForecastTextSize() {
    var theElement = document.getElementById('forecast00') ;

    let theFontSize = theElement.style.fontSize == startFontSize ;
    theElement.style.fontSize = theFontSize ;
    let rect = theElement.getBoundingClientRect() ;   // To see in debug
    theFontSize *= targetWidth / (theElement.offsetWidth / rightSide.offsetWidth) ;
    theElement.style.fontSize = round(theFontSize,2) + 'pt' ;
}

function updateTextSize() {
    var save ;
    timeFontSize = startFontSize ;
    tempFontSize = startFontSize ;
    timeElem.style.fontSize = timeFontSize ;
    tempElem.style.fontSize = tempFontSize ;

    // Hide temp element while sizing time element
    save = tempElem.style.display ;
    tempElem.style.display = 'none' ;
    timeFontSize *= targetWidth / (timeElem.offsetWidth / clockElem.offsetWidth) ;
    timeElem.style.fontSize = round(timeFontSize,2) + "pt" ;
    tempElem.style.display = save ;

    // Hide time element while sizing temp element
    save = timeElem.style.display ;
    timeElem.style.display = 'none' ;
    tempFontSize *= targetWidth / (tempElem.offsetWidth / clockElem.offsetWidth) ;
    tempElem.style.fontSize = round(tempFontSize,2) + 'pt' ;
    timeElem.style.display = save ;
    }


function round(value, precision) {
    var multiplier = Math.pow(10, precision || 0) ;
    return Math.round(value * multiplier) / multiplier ;
}

updateTextSize() ;
updateForecastTextSize() ;

multiclock.html

    <!DOCTYPE html>
    <html lang='en' style="height:100%; margin:0; padding:0">
    <head>
        <title>Full Screen Clock</title>
        <style>
            .box {
                display:flex;
                flex-flow: row nowrap;
                flex: none;
                align-items:center;
                justify-content:space-evenly;
                width:100%;
                height:100%;
            }
            .forecast {
                display:flex ;
                text-align:center ;
                width:100% ;
                flex:none ;
            }
        </style>

    </head>

    <body style="display:flex; height:100%; margin:0; padding:0; justify-content:center; align-items:center">

      <div id='page' class='box'>
      <div id='timeTempContainer' style='align-items:center; width:60%; display: flex; flex-flow:column nowrap; flex:none;'>
        <div id='clockDiv' style='font-size:85pt;text-align:center;vertical-align:middle;width:100%;flex:none;'>
          <span id="clocktext" style="font-kerning:none;">19:17</span>
        </div> <!-- clockDiv -->
        <div id='tempContainer' style='font-size:85pt;text-align:center;vertical-align:middle;width:100%;flex:none'>
          <span id="temptext" style="font-kerning:auto; text-align:center">39ºF 4ºC</span>
        </div> <!-- tempContainer -->
        <div id='otherCityContainer' style='font-size:85pt;text-align:center;vertical-align:middle;width:100%;flex:none'>
          <span id='othercity' style="font-kerning:auto; text-align:center">Eventually, we will size this</span>
        </div> <!-- otherCityContainer -->
      </div> <!-- timeTempContainer -->
      <div id='rightSideContainer'  style='flex-flow: column nowrap;justify-content:space-evenly;flex:none;'>
        <div> <span id='weatherIcon' class='forecast'><img alt='weatherIcon' style='vertical-align:middle' height=100 width=100 src='https://openweathermap.org/img/wn/[email protected]'></span> </div>
        <div> <span id='forecast00'  class='forecast'></span>20:00 38ºF 3ºC</div>
      </div> <!-- rightSideContainer -->
    </div> <!-- page -->


        <script src="multiclock-sample.js">

        </script>
    </body>
    </html>
0

There are 0 answers