5

So I have a matrix of divs within a container in my page, each div displays either a '1' or a '0'.

If I set my container to a width of 100% and height to fit the bottom of my page, I want to be able to scale all of the 1's and 0's inside the container's divs (the number of 0's and 1's will be a static number, lets go with 100 for the sake of this question) to always fit the container perfectly no matter what size the browser is resized to, so it fits the width and height of the container perfectly without any trailing white-space or elements that go off the page or trigger a scroll bar.

The goal is to make sure the fonts resize to fit within the container exactly, regardless of screen size (both height and width).

I have seen multiple similar questions on stack overflow, such as: JavaScript Scale Text to Fit in Fixed Div, but they all seem to scale a certain line of text rather than the text from my combined divs. Is there a way I can do this within JavaScript?

If you see what is being asked for in This Question, this is exactly what I want. The difference in that Q is that he uses some text within 1 div rather than multiple to fit his container.

Here is my HTML:

<div id="binaryMatrix" style="width: 100%; height: 100%;">
    <div>0</div>
    <div>1</div>
    <div>0</div>
    <div>1</div>
    <div>0</div>
    <div>1</div>
    <div>0</div>
    <div>1</div>
    ...up to 100
 </div>

Here is my CSS:

#binaryMatrix div {
    float: left;
}

See Fiddle: Fiddle

This project is also on GitHub: GitHub - danjonescidtrix/binary-matrix


Any help or advice here is appreciated, thank you in advance

Community
  • 1
  • 1
daniel aagentah
  • 1,672
  • 5
  • 29
  • 56

3 Answers3

1

I decided to have another go at this - not least because it's a fascinating problem.

I think I have cracked it.

var binaryMatrix = document.getElementById('binaryMatrix');
var binaryMatrixDivs = binaryMatrix.getElementsByTagName('div');

var largestNumberOfRows = 12;

for (var i = largestNumberOfRows; i > 0; i--) {
    if (binaryMatrixDivs.length % i === 0) {
        var numberOfRows = i;
        break;
    }
}

function changeDivWidth() {
    for (var i = 0; i < binaryMatrixDivs.length; i++) {
    var divWidth = (100 / (binaryMatrixDivs.length / numberOfRows));
    var divHeight = (100 / numberOfRows);

    binaryMatrixDivs[i].style.width = divWidth + 'vw';
    binaryMatrixDivs[i].style.height = divHeight + 'vh';
    binaryMatrixDivs[i].style.lineHeight = divHeight + 'vh';
    }
}

window.addEventListener('load',changeDivWidth,false);
body {
margin: 0;
padding: 0;
}

#binaryMatrix {
width: 100vw;
height: 100vh;
}

#binaryMatrix div {
display: inline-block;
float: left;
width: 0;
height: 0;
line-height: 20vh;
text-align: center;
}

#binaryMatrix div:nth-of-type(odd) {
background-color: rgb(191,191,191);
}

#binaryMatrix div:nth-of-type(even) {
background-color: rgb(127,127,127);
}
<div id="binaryMatrix">
<div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div>
</div>

Notes:

1) You can determine the number of rows by altering the value of numberOfRows. If the numberOfRows is set to 5, then there will always be 5 rows - no matter how short or tall or wide or narrow the window is.

2) Obviously, you'll want the numberOfRows to be a factor of the number of divs you have. So 5 rows is good if you have 100 divs or 90 divs, but if you have 96 divs, you'll want numberOfRows to be 4 or 6 or 12 or some other factor of 96.


Improvement:

The two notes above were necessary because in the first version of the script, you have to manually declare the number of rows. In the second version of the script (above) you can still manually declare the number of rows if you wish but (slightly less effort) you can simply manually declare the largest number of rows you wish to see (eg. no more than 14 rows) and the script will count down from 14 until it finds a factor - and the first factor it comes to will be the numberOfRows.

This will enable you to change the number of divs (manually or dynamically) without having to reset the numberOfRows each time.

Rounin
  • 27,134
  • 9
  • 83
  • 108
  • this is really good, do you think there's a way to do this with no padding or margin on any of the div elements, so instead of spacing the elements, they would actually get resized? – daniel aagentah Nov 15 '16 at 12:43
  • I have just thought of a way to improve it. We can determine the number of rows dynamically... hold up a second. – Rounin Nov 15 '16 at 12:44
  • No problem mate, if you need more of an idea, I have uploaded this to GitHub, so you can see what I am trying to create for yourself! https://github.com/danjonescidtrix/binary-matrix – daniel aagentah Nov 15 '16 at 12:45
  • Thank you - you can credit me on GitHub for the design I have put together above. I would appreciate it. My GitHub is https://github.com/rouninmedia Thanks. – Rounin Nov 15 '16 at 12:59
  • all I want is the 0's and 1's to resize to perfectly fit inside the outer container. So instead of spacing them out like you had done, I want them to resize if that makes sense. – daniel aagentah Nov 15 '16 at 13:02
  • look at this question http://stackoverflow.com/questions/24376897/fit-text-perfectly-inside-a-div-height-and-width-without-affecting-the-size-of?noredirect=1&lq=1, if you look at the picture example on the far right in the question, that is what I am looking to achieve. The only difference would be instead of the paragraph that he has used, it would be my 0's and 1's. – daniel aagentah Nov 15 '16 at 13:11
  • the difference is, in your solution, the numbers do not resize, they just simply space out from each other to fit the container. I want them all to be next to each other with no spacing, only FONT resizing. Does this make sense mate? – daniel aagentah Nov 15 '16 at 13:15
  • It basically wants to be like the far right picture in http://stackoverflow.com/questions/24376897/fit-text-perfectly-inside-a-div-height-and-width-without-affecting-the-size-of?noredirect=1&lq=1 , this s exactly what I want, only replacing the paragraph with my )'s and 1', the aim is to have all the 0's and 1's font-resize to fit the entire width and height of the outer container, – daniel aagentah Nov 15 '16 at 13:51
  • Aahhhh.... there was a vital piece of info in your question which I had not picked up on: **the number of 0's and 1's will be a static number** In the solution above I was focused all the time on the consideration that the number of digits was a variable and that the grid of divs would need to adapt to that. I'm going to start a new answer so as not to undo the work above - I really do have the answer now. – Rounin Nov 15 '16 at 15:05
1

Right. Third attempt (and I really do have it cracked this time).

The number of digits is static. Let's call it 100 digits.

Digits are taller than they are wide, so we need a grid of tall, narrow divs. 10x10 is no good. Let's set up a 20x5 grid instead.

Now all we need to do is work out:

  1. how large the digit font-size would be based only on the width of the viewport; and
  2. how large the digit font-size would be based only on the height of the viewport;

Whichever is the smaller can be the font-size applied to the digits.

var binaryMatrix = document.getElementById('binaryMatrix');
var binaryMatrixDivs = binaryMatrix.getElementsByTagName('div');

function applyNewFontSize() {

    var newVerticalFontSize = (window.innerHeight / 5.5);
    var newHorizontalFontSize = (window.innerWidth / 20.5);
    var newFontSize = (newVerticalFontSize > newHorizontalFontSize ? newHorizontalFontSize : newVerticalFontSize);

    for (var i = 0; i < binaryMatrixDivs.length; i++) {
    binaryMatrixDivs[i].style.fontSize = newFontSize + 'px';
    binaryMatrixDivs[i].style.lineHeight = newFontSize + 'px';
    }

}

window.addEventListener('resize',applyNewFontSize,false);
window.addEventListener('load',applyNewFontSize,false);
body {
margin: 0;
padding: 0;
}

#binaryMatrix {
width: 100vw;
height: 100vh;
}

#binaryMatrix div {
display: inline-block;
float: left;
width: 5vw;
height: 20vh;
text-align: center;
color: rgb(163,163,163);
}
<div id="binaryMatrix">
<div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div><div>0</div><div>1</div>
</div>
Rounin
  • 27,134
  • 9
  • 83
  • 108
  • this is awesome! I really appreciate your support on this, it's good to see active and inquisitive developers in the community. Also how could I eliminate the white space between each row when the font sizes are shrunk? – daniel aagentah Nov 15 '16 at 15:26
  • Ahh, I think simply removing the height property from the div would sort the white space between the rows! Nice. – daniel aagentah Nov 15 '16 at 15:34
  • I'm not going to be available until later tonight but I will check this in my project and then accept the answer, you've been very helpful mate and I will credit you on GitHub. – daniel aagentah Nov 15 '16 at 15:40
0

You can scale each element and then position its left value according to the new scale.

https://jsfiddle.net/f6Lfe8hv/2/

var total_width = 0;
var total_left = 0;
var $divs = $('#binaryMatrix>div');
var $binaryMatrix = $('#binaryMatrix');
var scale = 1;

$divs.each(function() {
  total_width += $(this).width();
});

function full_width() {

  scale = $binaryMatrix.width() / total_width;

  $divs.css('transform', 'scale(' + scale + ')');

  $divs.each(function() {

    $(this).css('left', total_left);

    total_left += $(this).width() * 1;

  });

  total_left = 0;
}

full_width();

$(window).resize(function() {

  full_width();

})
#binaryMatrix div {
  position: absolute;
  transform-origin: left;
}

#binaryMatrix {
  top:0;
  left:0;
  background: pink;
  position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div id="binaryMatrix" style="width: 100%; height: 100%;">

  <div>some_test_value</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>0</div>
  <div>1</div>
  <div>0</div>
  <div>1</div>
  <div>another_test_value</div>

</div>
Alvaro
  • 9,247
  • 8
  • 49
  • 76