skip to Main Content

How to make the dotted lines dynamic while having other functionalities (expand- collapse button on click of set1 or set2) intact. Do not want dotted line to go underneath data. So that it starts and ends like a connector between data. Fiddle showing the same: https://jsfiddle.net/vcjzn5hs/1/

Would appreciate your suggestion.

I am able to make dynamic dotted lines and expand-collapse work independently but not together. For your reference: Sample of how dynamic dotted lines should be http://jsfiddle.net/bwpugnd3/11/. But this example does not work along with expand collapse button.

Code snippet:

.flex {
  display: flex;
  justify-content: space-between;
}

.lev1,
.lev2,
.lev3 {
  position: relative;
  margin-top: 5px;
  margin-left: 15px;
}

.lev1::after,
.lev2::after,
.lev3::after {
  content: '';
  position: absolute;
  width: 80%;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin: 0 6px;
  height: 2px;
  color: lightgrey;
  margin-bottom: 4px;
  background-image: linear-gradient(to right, currentColor 2px, transparent 1px);
  background-size: 4px 2px;
}

.DataRightAlign {
  word-wrap: break-word;
  white-space: break-spaces;
  margin-right: 20px;
  margin-left: 10px;
  color: black;
}
<!--jquery and bootstrap-->

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
     <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>


<div class="itemDiv">
  <div>
    <a class="accordion-button " data-toggle="collapse" data-target=".lev1"> Set1 </a>
    <div class="collapse multi-collapse lev1 show">
      <p class="flex">
        <span>item1data</span>
        <span class="DataRightAlign"> Set1val here</span>
      </p>
    </div>
    <div class="collapse multi-collapse lev1 show">
      <p class="flex">
        <span>item2</span>
        <span class="DataRightAlign">Set1</span>
      </p>
    </div>
  </div>

  <div>
    <a class="accordion-button " data-toggle="collapse" data-target=".lev3">Set2 </a>
    <div class="collapse multi-collapse lev3 show">
      <p class="flex">
        <span>item3</span>
        <span class="DataRightAlign">Set2val</span>
      </p>
    </div>
  </div>

2

Answers


  1. This is something like table of contents CSS styling

    The basic idea is put content: '... very lengthy and make overflow hidden and make the div background of the left side text and right side text white, so those dots will not visible after or under the right side text or left side text, but actually the dotted line drawn for the entire row

    the height: 40px and top: -42px fixes the dotted line move slightly below the the left side text and right side text

    the z-index: -1; make the dotted line hide behind the right side text and left side text

    .toc {
    overflow: hidden;
    height: 40px;
    }
    
    .toc::after {
    content: '................................................................................................................................................................';
    overflow: hidden;
    position: relative;
    display: block;
    left: 0;
    top: -42px;
    z-index: -1;
    }
    .toc-title {
    background-color: #fff;
    padding-right: 1%;
    }
    .toc-section {
    background-color: #fff;
    padding-left: 1%;
    float: right;
    }
    <!--jquery and bootstrap-->
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
         <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    
        <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
        
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    
    <h1> Individual accordion collapse </h1>
    <br/>
    <div style="line-height: 40px">
    <h4 style="font-weight: 700" class="accordion-button" data-toggle="collapse" data-target=".lev1">Chapter 1: Some Chapter 1</h4>
    <div style="font-size: 25px;" class="collapse multi-collapse lev1 show">
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 1</span>
            <span class="toc-section">Section 1</span>
        </div>
      </div>
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 2</span>
            <span class="toc-section">Section 2</span>
        </div>
      </div>
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 3</span>
            <span class="toc-section">Section 3</span>
        </div>
      </div>
    </div>
    <h4 style="font-weight: 700" class="accordion-button" data-toggle="collapse" data-target=".lev2">Chapter 2: Some Chapter 2</h4>
    <div style="font-size: 25px;" class="collapse multi-collapse lev2 show">
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 1</span>
            <span class="toc-section">Section 1</span>
        </div>
      </div>
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 2</span>
            <span class="toc-section">Section 2</span>
        </div>
      </div>
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 3</span>
            <span class="toc-section">Section 3</span>
        </div>
      </div>
    </div>
    </div>
    <br/>
    <h1> Both accordion collapse </h1>
    <br/>
    <div style="line-height: 40px">
    <h4 style="font-weight: 700" class="accordion-button" data-toggle="collapse" data-target=".lev3">Chapter 1: Some Chapter 1</h4>
    <div style="font-size: 25px;" class="collapse multi-collapse lev3 show">
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 1</span>
            <span class="toc-section">Section 1</span>
        </div>
      </div>
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 2</span>
            <span class="toc-section">Section 2</span>
        </div>
      </div>
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 3</span>
            <span class="toc-section">Section 3</span>
        </div>
      </div>
    </div>
    <h4 style="font-weight: 700" class="accordion-button" data-toggle="collapse" data-target=".lev3">Chapter 2: Some Chapter 2</h4>
    <div style="font-size: 25px;" class="collapse multi-collapse lev3 show">
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 1</span>
            <span class="toc-section">Section 1</span>
        </div>
      </div>
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 2</span>
            <span class="toc-section">Section 2</span>
        </div>
      </div>
      <div>
        <div class="toc">
            <span class="toc-title">Some Title 3</span>
            <span class="toc-section">Section 3</span>
        </div>
      </div>
    </div>
    </div>
    Login or Signup to reply.
  2. One approach, and frankly the easiest, is below with explanatory comments in the code; please note that I removed all CSS from your own demo because it made it slightly easier to create the demo, but – of course – there’s nothing to stop you adding your own CSS back:

    /* a simple CSS reset to ensure the browser uses the same sizing
       algorithm for element sizes; including the width and padding
       within the declared sizes, also removing default margins
       and padding: */
    body {
      block-size: 100vh;
      padding-block: 1rem;
      padding-inline: 1.5rem;
    }
    
    .itemDiv {
      /* setting the inline-size of the element; inline-size is the axis
         on which inline-content (such as <span> elements) is laid out,
         and is perpendicular to the block-axis. In English the inline-axis
         is the horizontal axis running left-to-right. The clamp() function
         sets the preferred size of the element to 90%, with a 30rem
         minimum-size and 1100px maximum size: */
      inline-size: clamp(30rem, 90%, 1100px);
      /* centering the element on the inline-axis: */
      margin-inline: auto;
    }
    
    .flex {
      display: flex;
      gap: 0.5rem;
      /* spacing the elements out: */
      justify-content: space-between;
    }
    
    /* using the second span (noted in the HTML) to contain the line leading: */
    .flex > span:nth-child(2) {
      background-image:
        /* using a repeating-linear-gradient() as the background-image: */
        repeating-linear-gradient(
          /* 90degrees causes the gradient to run horizontally, from an
             origin on the left side: */
          90deg,
          /* currentColor is the currently-assigned color of the element, this
             runs from 0 to 2px: */
          currentColor 0 2px,
          /* and we switch to a transparent "color" which starts at 2px and
             runs for 3px until a point at 5px: */
          transparent 2px 5px
        );
      /* positioning the repeating-linear-gradient() at 0 on the inline axis,
         and at 100% minus 5px on the block-axis; 5px is something of a magic
         number to line the dots of the background image to the approximate
         baseline of the text in the adjacent elements: */
      background-position: 0 calc(100% - 5px);
      /* preventing the background from repeating: */
      background-repeat: no-repeat;
      /* setting the size of the background-image to be 100% of the width/inline-axis,
         and 2px on the vertical/block-axis: */
      background-size: 100% 2px;
      /* this causes the element to grow to fill all available space: */
      flex-grow: 1;
    }
    
    .accordion-button {
      /* if an element can be clicked, and is interactive, I tend to assign the
         following property and property-value to indicate that interactivity: */
      cursor: pointer;
    }
    <!--jquery and bootstrap-->
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    
    
    <!--html -->
    <div class="itemDiv">
    
      <div>
        <a class="accordion-button " data-toggle="collapse" data-target=".lev1"> Set1 </a>
        <div class="collapse multi-collapse lev1 show">
          <p class="flex">
            <span>item1data</span>
            <!-- I feel bad about it, but the easiest way is to add an element to hold
                 the leading: -->
            <span></span>
            <span class="DataRightAlign"> Set1val here</span>
          </p>
        </div>
        <div class="collapse multi-collapse lev1 show">
          <p class="flex">
            <span>item2</span>
            <span></span>
            <span class="DataRightAlign">Set1</span>
          </p>
        </div>
      </div>
    
    
      <div>
        <a class="accordion-button " data-toggle="collapse" data-target=".lev3">Set2 </a>
        <div class="collapse multi-collapse lev3 show">
          <p class="flex">
            <span>item3</span>
            <span></span>
            <span class="DataRightAlign">Set2val</span>
          </p>
        </div>
      </div>
      
    </div>

    JS Fiddle demo.

    An alternative is to use a CSS generated content to hold the leading (the dots that lie between the item-data and set-value), this has problems though; again, explanatory comments are in the code:

    /* a simple CSS reset to ensure the browser uses the same sizing
       algorithm for element sizes; including the width and padding
       within the declared sizes, also removing default margins
       and padding: */
    body {
      block-size: 100vh;
      padding-block: 1rem;
      padding-inline: 1.5rem;
    }
    
    .itemDiv {
      /* setting the inline-size of the element; inline-size is the axis
         on which inline-content (such as <span> elements) is laid out,
         and is perpendicular to the block-axis. In English the inline-axis
         is the horizontal axis running left-to-right. The clamp() function
         sets the preferred size of the element to 90%, with a 30rem
         minimum-size and 1100px maximum size: */
      inline-size: clamp(30rem, 90%, 1100px);
      /* centering the element on the inline-axis: */
      margin-inline: auto;
    }
    
    .flex {
      display: flex;
      gap: 0.5rem;
      /* spacing the elements out: */
      justify-content: space-between;
    }
    
    .flex > span:first-child {
      /* here we use display: contents, which emulates "unwrapping" of the content
         from the matched element, and placing it directly into its parent-element;
         this means that both the <span> content and the ::after pseudo-element can
         take part in the flex layout, acting as siblings: */
      display: contents;
    }
    
    /* using the second span (noted in the HTML) to contain the line leading: */
    .flex > span:first-child::after {
      background-image:
        /* using a repeating-linear-gradient() as the background-image: */
        repeating-linear-gradient(
          /* 90degrees causes the gradient to run horizontally, from an
             origin on the left side: */
          90deg,
          /* currentColor is the currently-assigned color of the element, this
             runs from 0 to 2px: */
          currentColor 0 2px,
          /* and we switch to a transparent "color" which starts at 2px and
             runs for 3px until a point at 5px: */
          transparent 2px 5px
        );
      /* positioning the repeating-linear-gradient() at 0 on the inline axis,
         and at 100% minus 5px on the block-axis; 5px is something of a magic
         number to line the dots of the background image to the approximate
         baseline of the text in the adjacent elements: */
      background-position: 0 calc(100% - 5px);
      /* preventing the background from repeating: */
      background-repeat: no-repeat;
      /* setting the size of the background-image to be 100% of the width/inline-axis,
         and 2px on the vertical/block-axis: */
      background-size: 100% 2px;
      content: '';
      /* this causes the element to grow to fill all available space: */
      flex-grow: 1;
    }
    
    .accordion-button {
      /* if an element can be clicked, and is interactive, I tend to assign the
         following property and property-value to indicate that interactivity: */
      cursor: pointer;
    }
    <!--jquery and bootstrap-->
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    
    
    <!--html -->
    <div class="itemDiv">
    
      <div>
        <a class="accordion-button " data-toggle="collapse" data-target=".lev1"> Set1 </a>
        <div class="collapse multi-collapse lev1 show">
          <p class="flex">
            <span>item1data</span>
            <span class="DataRightAlign"> Set1val here</span>
          </p>
        </div>
        <div class="collapse multi-collapse lev1 show">
          <p class="flex">
            <span>item2</span>
            <span class="DataRightAlign">Set1</span>
          </p>
        </div>
      </div>
    
    
      <div>
        <a class="accordion-button " data-toggle="collapse" data-target=".lev3">Set2 </a>
        <div class="collapse multi-collapse lev3 show">
          <p class="flex">
            <span>item3</span>
            <span class="DataRightAlign">Set2val</span>
          </p>
        </div>
      </div>
      
    </div>

    JS Fiddle demo.

    Unfortunately, the use of:

    .flex > span:first-child {
      display: contents;
    }
    

    means that we can no longer style the element with background-color, or border and so on; this is an unavoidable consequence of this approach.

    Finally, though, and thought of rather later than I’d like, we have the option of nesting flex-layouts as follows:

    /* a simple CSS reset to ensure the browser uses the same sizing
       algorithm for element sizes; including the width and padding
       within the declared sizes, also removing default margins
       and padding: */
    body {
      block-size: 100vh;
      padding-block: 1rem;
      padding-inline: 1.5rem;
    }
    
    .itemDiv {
      /* setting the inline-size of the element; inline-size is the axis
         on which inline-content (such as <span> elements) is laid out,
         and is perpendicular to the block-axis. In English the inline-axis
         is the horizontal axis running left-to-right. The clamp() function
         sets the preferred size of the element to 90%, with a 30rem
         minimum-size and 1100px maximum size: */
      inline-size: clamp(30rem, 90%, 1100px);
      /* centering the element on the inline-axis: */
      margin-inline: auto;
    }
    
    .flex {
      display: flex;
      gap: 0.5rem;
      /* spacing the elements out: */
      justify-content: space-between;
    }
    
    .flex > span:first-child {
      /* we assign display: flex to the element, this causes it to lay its
         own children out according to the flex layout properties: */
      display: flex;
      /* this causes the element to grow to fill all available space within
         its parent: */
      flex-grow: 1;
      /* we inherit the gap property from the parent, so that the gaps here
         are the same as the gaps between this element and its sibling(s): */
      gap: inherit;
    }
    
    .flex > span:first-child::after {
      /* again, using the background image to create the leading: */
      background-image:
        /* using a repeating-linear-gradient() as the background-image: */
        repeating-linear-gradient(
          /* 90degrees causes the gradient to run horizontally, from an
             origin on the left side: */
          90deg,
          /* currentColor is the currently-assigned color of the element, this
             runs from 0 to 2px: */
          currentColor 0 2px,
          /* and we switch to a transparent "color" which starts at 2px and
             runs for 3px until a point at 5px: */
          transparent 2px 5px
        );
      /* positioning the repeating-linear-gradient() at 0 on the inline axis,
         and at 100% minus 5px on the block-axis; 5px is something of a magic
         number to line the dots of the background image to the approximate
         baseline of the text in the adjacent elements: */
      background-position: 0 calc(100% - 5px);
      /* preventing the background from repeating: */
      background-repeat: no-repeat;
      /* setting the size of the background-image to be 100% of the width/inline-axis,
         and 2px on the vertical/block-axis: */
      background-size: 100% 2px;
      content: '';
      /* as with the parent element, we use flex-grow to allow the pseudo-element
         to grow to fill the available space: */
      flex-grow: 1;
    }
    
    .accordion-button {
      /* if an element can be clicked, and is interactive, I tend to assign the
         following property and property-value to indicate that interactivity: */
      cursor: pointer;
    }
    <!--jquery and bootstrap-->
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    
    
    <!--html -->
    <div class="itemDiv">
    
      <div>
        <a class="accordion-button " data-toggle="collapse" data-target=".lev1"> Set1 </a>
        <div class="collapse multi-collapse lev1 show">
          <p class="flex">
            <span>item1data</span>
            <span class="DataRightAlign"> Set1val here</span>
          </p>
        </div>
        <div class="collapse multi-collapse lev1 show">
          <p class="flex">
            <span>item2</span>
            <span class="DataRightAlign">Set1</span>
          </p>
        </div>
      </div>
    
    
      <div>
        <a class="accordion-button " data-toggle="collapse" data-target=".lev3">Set2 </a>
        <div class="collapse multi-collapse lev3 show">
          <p class="flex">
            <span>item3</span>
            <span class="DataRightAlign">Set2val</span>
          </p>
        </div>
      </div>
      
    </div>

    JS Fiddle demo.

    References:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search