2

I had a front-end interview a few months ago with the following problem and guideline:

  • You are given the baseline CSS, HTML, and JS
  • You are not allowed to directly edit the predefined HTML or CSS
  • You are allowed to add new CSS classes and use whatever version of jQuery you want or Vanilla JS

Goal 1: When you click the #container, divide the box (which is 400px by 400px) into four equal sized boxes.

Goal 2: When you click one of the boxes that were created in Goal 1, said box also divides into 4 equal sized boxes as well.

My Problem No matter what I do, the boxes do not divide perfectly. Not sure why inline-block isn't doing it's think, or what I can't append more than one node. Anyone have some expert tips?

var c = document.getElementById("container");

c.addEventListener("click", function(e) {
  var node = document.createElement("div");
  node.className = "boxxie";
  c.appendChild(node);
  c.appendChild(node);
  c.appendChild(node);
  c.appendChild(node);
})
*,
*:before,
*:after {
  box-sizing: border-box;
}

#container {
  border: 1px solid #2196f3;
  width: 400px;
  height: 400px;
}

.boxxie {
  display: inline-block;
  height: 50%;
  width: 50%;
  outline: 1px solid black;
}
<div id="container"></div>

Here is the jsfiddle https://jsfiddle.net/drewkiimon/fvx632ab/


Thanks to @wbarton, I was able to get this answer to work without using flexbox. I was adamant without using flexbox since I was pretty confident that it would not need it. Long and behold, there is a solution without it. By using float: left, we can avoid the vertical align, and by creating a for-loop where we re-create a "new" node, we can just append it four times. I also used a class with my div instead of a direct CSS selector on the div.

Thank you for all the help everyone! Case closed.

document.getElementById("container").addEventListener('click', function(e) {
 for (var i = 0; i < 4; i ++) {
   var node = document.createElement("div");
   node.className = "boxxie";
   e.target.appendChild(node);
  }
})
*,
*:before,
*:after {
  box-sizing: border-box;
}

#container {
  border: 1px solid #2196f3;
  width: 400px;
  height: 400px;
}

.boxxie {
  outline: 1px solid tomato;
  width: 50%;
  height: 50%;
  float: left;
}
<div id="container"></div>
drewkiimon
  • 591
  • 1
  • 9
  • 16
  • 1
    I have updated your question to include the pertinent parts of you jsfiddle. Please feel free to edit the runnable snippet to more accurately reflect what your actual code is doing. The code in your question didn't **exactly** reflect what was in the fiddle so they are merged in a way that I figured was correct, but you should check it make sure. Please try to include all pertinent code **in your question** and not on an external site. – zero298 Jul 11 '18 at 18:10

3 Answers3

4

My solution: https://jsfiddle.net/fvx632ab/106/

Added CSS:

div {
  display: flex;
  flex-grow: 0;
  flex-shrink: 0;
  outline: 1px solid #f33;
  width: 50%;
  flex-wrap: wrap;
}

Flexbox makes this easy for us, by defining some sensible layouts. We set the width of the child to 50%, and also enable wrapping so that we get two rows (since we're going to add four elements).

Then, in my JavaScript:

document.querySelector('body').addEventListener('click', (e) => {
  if (!e.target.matches('div')) {
    return;
  }
  for (let i=0; i<=3; i++) {
    e.target.appendChild(document.createElement('div'));
  }
});

We listen for clicks on the body (because we're going to be adding more divs later), but filter for only the selector we want, which is div. Then, we just add 4 children.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • Very nice! Unfortunately, as you start clicking boxes, it changes all of the other box sizes as well. I don't think my interviewer a few months back would accept this answer. You do solve the problem of adding all four boxes at once, which is very helpful! Thank you for that. – drewkiimon Jul 11 '18 at 18:20
  • @AndrewPagan Just change `border` to `outline` then. – Brad Jul 11 '18 at 18:23
  • outline worked perfectly! This is 100% the true answer. Do you think it would be possible to do it without flex? – drewkiimon Jul 11 '18 at 19:21
  • 2
    @drewkiimon Sure, I mean, I can hammer a nail with the blunt end of a screwdriver, but why do that when hammers are plentiful? – Brad Jul 11 '18 at 21:56
1

Here is my solution.

const c = document.getElementById("container");

c.addEventListener("click", e => {
  const target = e.target;

  for (let i = 0; i < 4; i++) {
    const child = document.createElement("div");
    target.appendChild(child);
  }
});
#container {
  width: 400px;
  height: 400px;
  border: 1px solid blue;
  box-sizing: border-box;
}

#container div {
  border: 1px solid red;
  display: inline-block;
  box-sizing: border-box;
  width: 50%;
  height: 50%;
  vertical-align: top;
  line-height: 1px;
}
<div id="container"></div>
zero298
  • 25,467
  • 10
  • 75
  • 100
1

Nothing new from a JS perspective but to answer @drewkiimon "is possible without flex?" This example uses floats.

document.querySelector('body').addEventListener('click', (e) => {
 if (!e.target.matches('div')) {
    return;
  }
  
  for (let i = 0; i < 4; i++) {
    e.target.appendChild(document.createElement('div'));
  }
})
*,
*:before,
*:after {
  box-sizing: border-box;
}

#container {
  border: 1px solid #2196f3;
  width: 400px;
  height: 400px;
}

/* ---------- */

#container div {
  float: left;
  width: 50%;
  height: 50%;
  outline: 1px solid tomato;
  background-color: rgba(64, 224, 208, .1);
}
<div id="container"></div>
wbarton
  • 126
  • 6