htmlcssepub3

Cannot Use E::before and calc() in ePub CSS Need Alternatives


My original CSS works with most ereaders but fails with Kindle because you cannot use psuedo elements ::before and calc:


.timeline {
 position: relative;
 padding: 0;
 margin: 0;
 display: flex;
 display: -webkit-flex;
 flex-direction: column;
 -webkit-flex-direction: column;
}

.timeline-group {
 position: relative;
 margin-bottom: 2em;
 padding-left: 2em;
 page-break-inside: avoid;
 break-inside: avoid;
}

.timeline-event::before {
    content: "";
    height: 2px;
    width: 1.5em; /* Adjust the width to match the left padding */
   background-color: orange;
    position: absolute;
    left: -2em;
    top: 30%; /* Adjust to align with the content */
  break-inside: avoid; /* Ensure events don't break across pages */
  page-break-inside: avoid;
 } 
 
.timeline-event {
  position: relative;
  margin: 1em 0;
  padding-left: 2em;
  bottom:0;
  break-inside: avoid; /* Ensure events don't break across pages */
  page-break-inside: avoid;
}

.timeline-content {
    padding: 1em;
    margin: 0 1em 0 -2.5em;
    background-color: #EFEFEF;
    border-left: 5px solid #425695;
    border-radius: 0.5em;
    break-inside: avoid; /* Ensure events don't break across pages */
    page-break-inside: avoid;
}

.timeline-event h3 {
    margin: 0 0 0.5em 0;
    font-size: 1.2em;
}

.timeline-event p {
    margin: 0;
}


.timeline-year::before {
   content: '';
   position: absolute;
   top: 2.0rem; /* Adjust this value to match the padding/margin of timeline-year */
  left: 0;
   bottom: 0; /* Extend the line to the bottom of the parent */
   height: calc(100vh - 62px); /* calc() No work on Kindle */
   height: -moz-calc(100% - 62px);
   height: -webkit-calc(100% - 62px);
   width: 2px;
   background-color: #ff0000;
}

.timeline-year {
  /* inline-size: fit-content; No Work with Kindle*/
  display: inline-block;
  width: 2.5em;
  padding: .25rem .75rem;
  background-color: #425695;
  font-size: 1.5em;
  color: #ffffff;
  margin-bottom: 1em;
}

.timeline-date {
  display: inline-block;
  width: auto;
  padding: .25rem 1.25rem .25rem;
  margin-bottom: .5em;
  background-color:  #ffffff;
  font-weight: 700;
  font-size: .75rem;
  text-transform: uppercase;
  color: currentColor;
}


body.timeline02 {
  font-family: var(--ds-typography-main-font-family, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Open Sans, Ubuntu, Fira Sans, Helvetica Neue, sans-serif);
  font-size: var(--ds-typography-main-font-size, .75rem);
  color: var(--ds-typography-main-color, #222);
  line-height: var(--ds-typography-main-line-height, 1.75);
  background-color: #ffffff;
  margin: 0;
}

My HTML looks like:

 <section class="timeline">

    <div class="timeline-year" aria-hidden="true">1840</div>
     <div class="timeline-group">
        <div class="timeline-event">
            <div class="timeline-content">
            <div class="timeline-date">
                <time datetime="1840-03-01">01 March 1840</time>
            </div>
                <h3>Birth of Some Guy</h3>
                <p>3rd son born to a family in Ohio.</p>
            </div> <!--End timeline-content -->
        </div> <!--End timeline-event -->
    </div> <!-- End 1840 timeline-group -->

  <div class="timeline-year" aria-hidden="true">1858</div>
     <div class="timeline-group">
        <div class="timeline-event">
            <div class="timeline-content">
            <div class="timeline-date">
                <time datetime="1858-01-01">1858</time>
            </div>
                <h3>Uncle Moves to Iowa</h3>
                <p>Uncle moves to Iowa and settles in Linn County, Iowa. </p>
            </div> <!--End timeline-content -->
        </div> <!--End timeline-event -->

        <div class="timeline-event">
            <div class="timeline-content">
            <div class="timeline-date">
                <time datetime="1858-01-01">1858</time>
            </div>
                <h3>Uncle Becomes Mayor</h3>
                <p>Uncle becomes Mayor in some city.</p>
            </div> <!--End timeline-content -->
        </div> <!--End timeline-event -->

    </div> <!-- End 1858 timeline-group -->

 <div class="timeline-year" aria-hidden="true">END</div>

</section> <!-- End timeline section-->

How can i change this to eliminate the use of pseudo E::before and calc() in the css with an alternative CSS method (no javascript allowed either) but still have it look the same? My code was based on original by https://codepen.io/melnik909/pen/qPjwvq Skin #3


Solution

  • Instead of having pseudo elements, simple add an element and selector and call on that elements selector and style accordingly.

    Not having calc() available really makes things somewhat static, so you will have to use static measurements adding the heights and margins of each element to get the height of the timeline-line.

    For the ::before timeline line that connects the dates, just place an element (I use a DIV in my example) within the positioned relative parent and then make it absolute and place it where you need to using left/top. Then style its height/width, etc...

    Part of the issue is your timeline-group / timeline-content's height is content driven on context of height and can change, so the only way would be to use a static height for each of these, but you would likely need to constrain the amount of content that can be inserted into each of the content lines in order to always have the same height per section, otherwise things could break if you are not keeping a close eye on that. Then you can use a css variable for each timeline-content height.

    See notes in CSS on height of timeline...

    .timeline {
      position: relative;
      padding: 0;
      margin: 0;
      display: flex;
      display: -webkit-flex;
      flex-direction: column;
      -webkit-flex-direction: column;
      --content-height: 5rem;
      --timeline-line: 524px;
      /* timeline-line height 
          from top to bottom:
          timeline years bottom margin = 24px
           1em default = 16px
          timeline-event -> margin 1em for top and bottom = 32px
          timeline-content -> padding 1em = 32px for top and bottom
                           -> height = 5rem (5 X 16 = 80px + 32px) = 120px
          timeline-year -> 28 + padding 4px top and bottom = 36px + bottom margin of 24px = 60px      
          timeline-group -> margin-bottom = 32px
          timeline-content -> padding 1em = 32px for top and bottom
                           -> height = 5rem (5 X 16 = 80px + 32px) = 120px    
          timeline-content -> padding 1em = 32px for top and bottom
                           -> height = 5rem (5 X 16 = 80px + 32px) = 120px
          24 + 16 + 32 + 120 + 60 + 32 + 120 + 120 = 524
          */
    }
    
    .timeline-line {
      position: absolute;
      width: 2px;
      background-color: #f00;
      top: 2.2rem;
      margin-left: 0;
      height: var(--timeline-line);
    }
    
    .timeline-group {
      position: relative;
      margin-bottom: 2em;
      padding-left: 2em;
      page-break-inside: avoid;
      break-inside: avoid;
    }
    
    .timeline-connector {
      height: 2px;
      width: 1.5em;
      /* Adjust the width to match the left padding */
      background-color: orange;
      position: absolute;
      left: -2em;
      top: 30%;
      /* Adjust to align with the content */
      break-inside: avoid;
      /* Ensure events don't break across pages */
      page-break-inside: avoid;
    }
    
    .timeline-event {
      position: relative;
      margin: 1em 0;
      padding-left: 2em;
      bottom: 0;
      break-inside: avoid;
      /* Ensure events don't break across pages */
      page-break-inside: avoid;
    }
    
    .timeline-content {
      padding: 1em;
      margin: 0 1em 0 -2.5em;
      background-color: #EFEFEF;
      border-left: 5px solid #425695;
      border-radius: 0.5em;
      break-inside: avoid;
      /* Ensure events don't break across pages */
      page-break-inside: avoid;
      height: var(--content-height);
    }
    
    .timeline-event h3 {
      margin: 0 0 0.5em 0;
      font-size: 1.2em;
    }
    
    .timeline-event p {
      margin: 0;
    }
    
    .timeline-year {
      /* inline-size: fit-content; No Work with Kindle*/
      display: inline-block;
      width: 2.5em;
      padding: .25rem .75rem;
      background-color: #425695;
      font-size: 1.5em;
      color: #ffffff;
      margin-bottom: 1em;
    }
    
    .timeline-date {
      display: inline-block;
      width: auto;
      padding: .25rem 1.25rem .25rem;
      margin-bottom: .5em;
      background-color: #ffffff;
      font-weight: 700;
      font-size: .75rem;
      text-transform: uppercase;
      color: currentColor;
    }
    
    body.timeline02 {
      font-family: var(--ds-typography-main-font-family, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Open Sans, Ubuntu, Fira Sans, Helvetica Neue, sans-serif);
      font-size: var(--ds-typography-main-font-size, .75rem);
      color: var(--ds-typography-main-color, #222);
      line-height: var(--ds-typography-main-line-height, 1.75);
      background-color: #ffffff;
      margin: 0;
    }
    <section class="timeline">
      <!--/ added this element for timeline-line /-->
      <div class="timeline-line"></div>
      <div class="timeline-year" aria-hidden="true">1840</div>
      <div class="timeline-group">
        <div class="timeline-event">
          <!--/ added this element for timeline-connector /-->
          <div class="timeline-connector"></div>
          <div class="timeline-content">
            <div class="timeline-date">
              <time datetime="1840-03-01">01 March 1840</time>
            </div>
            <h3>Birth of Some Guy</h3>
            <p>3rd son born to a family in Ohio.</p>
          </div>
          <!--End timeline-content -->
        </div>
        <!--End timeline-event -->
      </div>
      <!-- End 1840 timeline-group -->
    
      <div class="timeline-year" aria-hidden="true">1858</div>
      <div class="timeline-group">
        <div class="timeline-event">
          <!--/ added this element for timeline-connector /-->
          <div class="timeline-connector"></div>
          <div class="timeline-content">
            <div class="timeline-date">
              <time datetime="1858-01-01">1858</time>
            </div>
            <h3>Uncle Moves to Iowa</h3>
            <p>Uncle moves to Iowa and settles in Linn County, Iowa. </p>
          </div>
          <!--End timeline-content -->
        </div>
        <!--End timeline-event -->
    
        <div class="timeline-event">
          <!--/ added this element for timeline-connector /-->
          <div class="timeline-connector"></div>
          <div class="timeline-content">
            <div class="timeline-date">
              <time datetime="1858-01-01">1858</time>
            </div>
            <h3>Uncle Becomes Mayor</h3>
            <p>Uncle becomes Mayor in some city.</p>
          </div>
          <!--End timeline-content -->
        </div>
        <!--End timeline-event -->
      </div>
      <!-- End 1858 timeline-group -->
    
      <div class="timeline-year" aria-hidden="true">END</div>
    
    </section>
    <!-- End timeline section-->