Search code examples
htmlcsstwitter-bootstraptwitter-bootstrap-3

Pushing second column to next row if text in first column is long


I'm using Bootstrap 3. I have 2 column in 1 row. How do I push the column in second column to next row if text in 1st row is longer than 1 row? Here is my code and the Lorem Ipsum text in 1st column is short, so the output is what I want:

<div class="col-sm-12">
  <div class="panel panel-default">
    <header class="panel-heading">
      <i class="fa fa-folder-o text-success fa-fw"></i> Basic Info <span class="text-success pull-right">
        <b></b>In Use </span>
    </header>
    <div class="panel-body">
      <div class="row">
        <div class="col-sm-12">
          <div class="col-sm-6 col-xs-12">
            <div class="row m-t-8 m-b-8">
              <div class="col-sm-6 col-xs-12"> Agenci </div>
              <div class="col-sm-6 col-xs-12">
                <span class="text-primary">What is Lorem Ipsum</span>
              </div>
            </div>
          </div>
          <div class="col-sm-6 col-xs-12">
            <div class="row m-t-8 m-b-8">
              <div class="col-sm-6 col-xs-12"> Department </div>
              <div class="col-sm-6 col-xs-12">
                <span class="text-primary"> Retail Audit </span>
              </div>
            </div>
          </div>
          <div class="col-sm-6 col-xs-12">
            <div class="row m-t-8 m-b-8">
              <div class="col-sm-6 col-xs-12"> PTJ Paid </div>
              <div class="col-sm-6 col-xs-12">
                <span class="text-primary">10000001</span>
              </div>
            </div>
          </div>
          <div class="col-sm-6 col-xs-12">
            <div class="row m-t-8 m-b-8">
              <div class="col-sm-6 col-xs-12"> PTJ Responsible </div>
              <div class="col-sm-6 col-xs-12">
                <span class="text-primary">348812</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Here is working jsfiddle : https://jsfiddle.net/od6eup8w/

If the Lorem Ipsum text is longer than one line, it would drop to second line like in the picture. Not the output I want.

enter image description here

I want the Lorem Ipsum text to occupied the whole line like second picture below and push the second column Department down:

enter image description here


Solution

  • You can use javascript to place the text string you wish to compare into a temporary span element, then use the bounding client rect width to see if there is an overflow of the temporary span element.

    If you get overflow, swap out the classes in the affected elements to the boot strap classes that will style as you wish.

    See the descriptions in the snipit for a more detailed explanation.

    Keep in mind I used boptstrap grid cols sm. If you want it to be truly dynamic in all grid system options, you would need to accommodate each grid options available in BS3.

    const textEls = document.querySelectorAll('.text-primary');
    
    // helper function
    const addRemoveClassLists = (el, removeCls, addCls) => {
      el.classList.add(addCls);
      el.classList.remove(removeCls);
    }
    
    const checkOverflow = (els) => {
      els.forEach(text => {
        // create a span hold the text string so we can compare the widths
        const compDiv = document.createElement('span');
        // append it to your document body
        document.body.append(compDiv);
        // set it's textContent to the text content of the text string we wish to compare
        compDiv.textContent = text.textContent;
        // get the bounding rect width of the comparative span
        const rectCompWidth = compDiv.getBoundingClientRect().width;
        // now get the bounding rect width of the text elements parent (includes padding/margin)
        const rectParentWidth = text.parentElement.getBoundingClientRect().width;
        // now identify and set a variable to the closest rows parent element up the HTML chain
        const targetRowParent = text.closest('.row').parentElement;
        // get the title element 
        const title = text.closest('.row').children[0];
        // get the text elements parent
        const titleText = text.closest('.row').children[1];
        // a conditional to check the width of the text parent element 
        // to that of the comparative elements width
        if (rectCompWidth > rectParentWidth) {
          // run relavent elements through helper function to change classes and display as wanted
          addRemoveClassLists(title, 'col-sm-6', 'col-sm-3');
          addRemoveClassLists(titleText, 'col-sm-6', 'col-sm-9');
          addRemoveClassLists(targetRowParent, 'col-sm-6', 'col-sm-12');
        } else {
          addRemoveClassLists(title, 'col-sm-3', 'col-sm-6');
          addRemoveClassLists(titleText, 'col-sm-9', 'col-sm-6');
          addRemoveClassLists(targetRowParent, 'col-sm-12', 'col-sm-6');
        }
        // remove comparative element from DOM
        compDiv.remove();
      })
    }
    
    // run function and pass in text element
    checkOverflow(textEls);
    @import url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css');
    <div class="col-sm-12">
      <div class="panel panel-default">
        <header class="panel-heading">
          <i class="fa fa-folder-o text-success fa-fw"></i> Basic Info <span class="text-success pull-right">
            <b></b>In Use </span>
        </header>
        <div class="panel-body">
          <div class="row">
            <div class="col-sm-12">
              <div class="col-sm-6 col-xs-12">
                <div class="row m-t-8 m-b-8">
                  <div class="col-sm-6 col-xs-12"> Agenci </div>
                  <div class="col-sm-6 col-xs-12">
                    <span class="text-primary">Lorem Ipsum text here that is a bit long and overflowing</span>
                  </div>
                </div>
              </div>
              <div class="col-sm-6 col-xs-12">
                <div class="row m-t-8 m-b-8">
                  <div class="col-sm-6 col-xs-12"> Department </div>
                  <div class="col-sm-6 col-xs-12">
                    <span class="text-primary"> Retail Audit </span>
                  </div>
                </div>
              </div>
              <div class="col-sm-6 col-xs-12">
                <div class="row m-t-8 m-b-8">
                  <div class="col-sm-6 col-xs-12"> PTJ Paid </div>
                  <div class="col-sm-6 col-xs-12">
                    <span class="text-primary">10000001</span>
                  </div>
                </div>
              </div>
              <div class="col-sm-6 col-xs-12">
                <div class="row m-t-8 m-b-8">
                  <div class="col-sm-6 col-xs-12"> PTJ Responsible </div>
                  <div class="col-sm-6 col-xs-12">
                    <span class="text-primary">348812</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="panel-body">
          <div class="row">
            <div class="col-sm-12">
              <div class="col-sm-6 col-xs-12">
                <div class="row m-t-8 m-b-8">
                  <div class="col-sm-6 col-xs-12"> Agenci </div>
                  <div class="col-sm-6 col-xs-12">
                    <span class="text-primary">Some short text</span>
                  </div>
                </div>
              </div>
              <div class="col-sm-6 col-xs-12">
                <div class="row m-t-8 m-b-8">
                  <div class="col-sm-6 col-xs-12"> Department </div>
                  <div class="col-sm-6 col-xs-12">
                    <span class="text-primary"> Retail Audit </span>
                  </div>
                </div>
              </div>
              <div class="col-sm-6 col-xs-12">
                <div class="row m-t-8 m-b-8">
                  <div class="col-sm-6 col-xs-12"> PTJ Paid </div>
                  <div class="col-sm-6 col-xs-12">
                    <span class="text-primary">10000001</span>
                  </div>
                </div>
              </div>
              <div class="col-sm-6 col-xs-12">
                <div class="row m-t-8 m-b-8">
                  <div class="col-sm-6 col-xs-12"> PTJ Responsible </div>
                  <div class="col-sm-6 col-xs-12">
                    <span class="text-primary">348812</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>