Search code examples
htmlcsscss-transforms

How to translateX an element proportionally to its own width and not its parent or screen width with pure CSS


I am trying to adapt this pure CSS text scroll tutorial to my project. I found that it does not work when scrolled element width is longer than its container width. It stops scrolling too early while element is still visible.

I examined it a bit and managed to identify the problem but it is difficult for me to fix it as I do not really know much about CSS. Reason why it does not work is the final translateX(-100%) moves text by 100% of the container size, not the scrolled element size. This causes the animation to reset while text is still visible.

Please take a look at the snippet I prepared here below

.container {
  width: 200px;
  border: 1px solid black;
  overflow: hidden;
  white-space: nowrap;
}
.content {
  transformBox: content-box;
  MozTransform: translateX(-100%);
  WebkitTransform: translateX(-100%);
  transform: translateX(-100%);
}
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div class="container">
            <div class="content">
                now this is just some crazy long text, much wider than its parent container
            </div>
        </div>
    </body>
</html>

The expected result is: text should not be visible because it should be moved entirely to the left outside of the screen by transformX(-100%).

I think if someone finds how to transformX(-100%) by the element width, that would fix the problem with the scroller. I was researching it a bit and I found transform-box property that indicates the reference element to the CSS transform function. I did try all the possible values but it did not make any change and now I am out of ideas.


Solution

  • You need to use width into content rule width: fit-content;

    .container {
      width: 200px;
      border: 3px solid black;
      border-radius: 5px;
      overflow: hidden;
      white-space: nowrap;
    }
    
    .content {  
      /* animation properties */  
      width:fit-content;
      -moz-animation: my-animation 15s linear infinite;
      -webkit-animation: my-animation 15s linear infinite;
      animation: my-animation 15s linear infinite;
    }
    
    /* for Firefox */
    @-moz-keyframes my-animation {
      from { -moz-transform: translateX(100%); }
      to { -moz-transform: translateX(-100%); }
    }
    
    /* for Chrome */
    @-webkit-keyframes my-animation {
      from { -webkit-transform: translateX(100%); }
      to { -webkit-transform: translateX(-100%); }
    }
    
    @keyframes my-animation {
      from {
        -moz-transform: translateX(100%);
        -webkit-transform: translateX(100%);
        transform: translateX(100%);
      }
      to {
        -moz-transform: translateX(-100%);
        -webkit-transform: translateX(-100%);
        transform: translateX(-100%);
      }
    <!DOCTYPE html>
    <html>
        <head>
        </head>
        <body>
            <div class="container">
                <div class="content">
                    now this is just some crazy long text, much wider than its parent container
                </div>
            </div>
        </body>
    </html>

    fit-content(<length-percentage>)
    

    Uses the fit-content formula with the available space replaced by the specified argument, i.e. min(max-content, max(min-content, ))

    Reference: