javascripthtmlcssdat.gui

Centering two buttons into child div of a parent div


I am using dat.gui.js to have a parameters menu with Three.js. I would like to put this menu on the top-right of main window. Moreover, I would like to add 2 buttons at the bottom of this menu which have to be centered horizontally and relatively to the parent div.

Here's an example in JS Fiddle.

As you can see, into HTML, I have the following structure for child and parent div:

<div id="webgl">
<div id="global-ui">
 <div id="gui">
 </div>
 <div id="buttons">       
         <button type="button" id="startButtonId" class="btn btn-primary" tabindex="13">Start Animation</button>
         <button type="button" id="resetButtonId" class="btn btn-default" tabindex="14">Reset</button>
 </div>
 </div>
</div>

with the CSS for #gui:

gui.domElement.id = 'gui';

which corresponds to:

#global-ui {position: relative;}
#gui {position: absolute; top: 0; right: 0;}
#buttons {position: absolute; top: 200px;}
 

#global-ui div represents the parent div of #gui div and #buttons div.

With this css, I get the following image:

result with above code

and I would like to get this:

image to get

As you can see on the first image, there are 2 issues : first, the DAT.GUI is not located strictly on the right and top even with CSS "#gui {position: absolute; top: 0; right: 0;}". It seems there is a margin on the right.

Second problem, the two buttons are not centered relatively to DAT.GUI, I tried using "margin: 0 auto;" or with "text-align: center;" but without success. I want to center it relatively to #gui div container and with an automatic way.

How can I solve these two issues?


Solution

  • As for the spacing to the right of the controls, your #gui element has a right margin of 15px, so you can correct this by adding margin-right:0; to the CSS rules for #gui:

    #gui {position: absolute; top: 0; right: 0; margin-right:0;}
    

    As for aligning the elements to be centered, I've broken it down here:

    Theory

    In order to center something like div, the way to do it with CSS is to have the child element use margin-right and margin-left both set to auto, and the parent element needs to be wide enough to fill the area area you want the containers to be centered inside.

    Solution

    The width of the container (in this case #buttons) is only as wide as the buttons inside it make it, so there's not enough width for the buttons to be able to be centered if you were to simply do this:

    #button {
      margin-left: auto;
      margin-right: auto;
    }
    

    Therefore, the width #buttons container has to be increased so that it is as wide as you need it to be, in this case, to be as wide as the #gui element, but doing just that still doesn't let the buttons be centered because there are two of them, so you need a wrapper element inside which creates space inside for the buttons to center within. This looks like this in the DOM:

    <div id="buttons-wrapper">
      <div id="buttons">
        <button type="button" id="startButtonId" class="btn btn-primary" tabindex="13">Start Animation</button>
        <button type="button" id="resetButtonId" class="btn btn-default" tabindex="14">Reset</button>
      </div>
    </div>
    

    And then #buttons-wrapper needs to be set to the width of #gui (the target width of the space which the buttons should be centered), and #buttons needs to be set to a width which is equal to the sum of the child containers #startButtonId and #resetButtonId, and then margin-right and margin-left can finally be applied to #buttons and it will work as expected.

    To set the width dynamically, you've got to use JavaScript and measure the widths of the containers you need:

    document.getElementById('buttons-wrapper').style.width = gui.width + 'px';
    target_width = 5;  // a couple pixels extra
    target_width = target_width + document.getElementById('startButtonId').offsetWidth;
    target_width = target_width + document.getElementById('resetButtonId').offsetWidth;
    document.getElementById('buttons').style.width = target_width + 'px';
    

    I've put the complete solution for your specific case into this fiddle: http://jsfiddle.net/bnbst5sc/4/

    enter image description here

    Generic Solution

    Here it is outside the context of your solution, as a general case:

    #outer-wrapper {
      position: absolute;
      top: 100px;
      left: 150px;
      width: 300px;
      padding: 10px 0;
      background-color: #ff0000;
    }
    #inner-wrapper {
      margin-left: auto;
      margin-right: auto;
      width: 175px;
      padding: 10px 0;
      background-color: #00ff00;
    }
    button {
      display: inline-block;
      float: left;
    }
    #btn1 {
      background-color: #f0f000;
      width: 100px;
    }
    #btn2 {
      background-color: #00f0f0;
      width: 75px;
    }
    <div id="outer-wrapper">
      <!-- #outer-wrapper, has an arbitrary width -->
      <div id="inner-wrapper">
        <!-- #inner-wrapper, as wide as the sum of the widths of #btn1 and #btn2 and has margin-left and margin-right set to auto-->
        <button id="btn1">Button 1</button>
        <button id="btn2">Button 2</button>
      </div>
    </div>