#StackBounty: #javascript #html #css #css-animations #onscroll How to get exact scroll position when animating elements onScroll

Bounty: 100

I am trying to animate elements while scrolling based on the elements progress through the scene. I am running into the issue of the browser returning intermittent scroll positions making it difficult to be exact when starting and stopping element animation.

Minimal example:

Fiddle Fiddle Demo

const tweens = document.querySelectorAll('.tween');
const trigger = document.querySelector('.start');
const triggerRect = trigger.getBoundingClientRect();

let yScroll = window.scrollY;
let yCurrent = yScroll;
let AF = null;

const start = triggerRect.top - yScroll - 200;
const end = start + 400;

const updateScroll = () => {
    yScroll = window.scrollY;
  startAnimation();
}

const startAnimation = () => {
  if(!AF) AF = requestAnimationFrame(animate)
}

const cancelAnimation = () => {
  yCurrent = yScroll;
  cancelAnimationFrame(AF);
  AF = null;
}

const animate = () => {
  if(yCurrent === yScroll) cancelAnimation();
  else {
    updateElements();
    yCurrent = yScroll;
    AF = requestAnimationFrame(animate);
  }
}

const updateElements = () => {
  const pos = yCurrent - start;
  if(inScene()){
    tweens[0].style.transform = `translateX(${pos}px)`;
    tweens[1].style.transform = `translateY(${pos}px)`;
  }
}

const inScene = () => {
  return start <= yCurrent && end >= yCurrent ? true : false;
};


window.addEventListener('scroll', updateScroll);
.wrapper{
  position:relative;
  margin: 100vh 20px;
  background: rgb(240,240,240);
  height: 900px;
  border: 1px solid red;
}

.line{
  position:absolute;
  left: 0;
  width: 100%;
  height: 1px;
  background: red;
}

.start{
  top: 200px;
}

.end{
  bottom: 200px;
}

.tween{
  position:absolute;
  top:200px;
  width: 100px;
  height: 100px;
  background: blue;
}

.left{
  left: 0;
}

.right{
  right: 0;
}
<h1>Scroll Down</h1>
<div class="wrapper">
  <div class="line start trigger"></div>
  <div class="line end"></div>
  <div class="tween left"></div>
  <div class="tween right"></div>
</div>

As you can see the elements are supposed to stop on the lines but when you scroll they never really do. And the faster you scroll the worse it becomes.

So is there a technique to either return the correct scroll position or somehow debounce the elements so then can reach the full range when scrolling instead of constantly coming up short of their intended position?

I know this is possible because scrolling libraries like ScrollMagic do a pretty good job of handling this but I don’t really want to deconstruct then entire ScrollMagic framework to find out how they achieve it. I would use the ScrollMagic framework itself but I am trying to have a momentum style scrolling container wrapping the page and translating it on scroll along with elements inside this container and using ScrollMagic it is pretty buggy. So I figured I would post the question here and see if anyone had any experience or insight on the situation.

Any guidance would be appreciated as I have been mulling over this for a while.


Get this bounty!!!

#StackBounty: #html #css #height How to remove random jump on image when zooming in on it

Bounty: 200

when I press on an image its supposed to blow up into a larger picture. However, I changed the size so the image isn’t fully touching the bottom and top of the screen by changing the height to 90vh. However, now when I press the image you can see it shift up that 10vh before expanding the image. Can someone help me remove that jump?

https://darrientu.com/

    .pswp {  height:100vh !important;
margin:auto!important;top:0 !important;
    bottom:0 !important;
}

.pswp__scroll-wrap {
height:90vh !important;margin:auto!important;top:0 !important;
    bottom:0 !important;
}


Get this bounty!!!

#StackBounty: #html #css #html-table #css-position #absolute Table with fixed position of columns without setting height and width of t…

Bounty: 150

I have a table with fixed first three columns. My first three columns are fixed. What I want is that the rest columns should calculate their height and width automatically, based on their content.

So my CSS looks like this:

.outer {
  position:relative;
  background-color: hotpink;
}
.inner {
  overflow-x:scroll;
  overflow-y: visible;
  width: calc(100% - 1500px);
  margin-left: 25.3em;
  background-color: greenyellow;
}

table {
  table-layout: fixed;
  width: 100%;
}

td, th {
  vertical-align: top;
  border-top: 1px solid #ccc;
  padding: 0.8em;
  width:6em;
  height: 4em;
}

.col1 {
  position:absolute;
  left: 0em;
  width: 6em;
}

.col2 {
  position:absolute;
  left: 6em;
  width: 6em;
}

.col3 {
  position:absolute;
  left: 12em;
  width: 6em;
}

This is HTML of table:

<div class="outer">
    <div class="inner">
      <table>
        <tr>
          <th class="col1">Header A1</th>
          <th class="col2">Header A</th>
          <th class="col3">Header A</th>

          <td>col 2 - A (WITH LONGER CONTENT)</td>
          <td>col 3 - A</td>
          <td>col 4 - A</td>
          <td>col 5 - A</td>
        </tr>
        <tr>
          <th class="col1">This row should be empty</th>
          <th class="col2">This row should be empty</th>
          <th class="col3">This row should be empty</th>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <th class="col1">Header B</th>
          <th class="col2">Header B</th>
          <th class="col3">Header B</th>

          <td>col 2 - B 123345</td>
          <td>col 3 - B</td>
          <td>col 4 - B</td>
          <td>col 5 - B</td>

        </tr>
        <tr>
          <th class="col1">Header C</th>
          <th class="col2">Header C</th>
          <th class="col3">Header C</th>

          <td>col 2 - C/td>
          <td>col 3 - C</td>
          <td>col 4 - C</td>
          <td>col 5 - C</td>
        </tr>
      </table>
    </div>
  </div>

Is it possible to avoid setting width and height in td, th?

I mean to avoid this hardcoded values of height and width:

td, th {
  ...
  width:6em;
  height: 4em;
}

Is it possible to do just with plain CSS without JavaScript? If it is not possible to implement with this solution, it would be really great to see another approach.


Get this bounty!!!

#StackBounty: #css #angular #typescript #angular-material #angular8 Angular 8: Change Height in Mat-form-field to Specific pixel number

Bounty: 50

How can I change height in mat-form-field with appearance="outline" to a specific height pixel number, 40px (or any required number from UX team in the future). I need to reduce the mat-form-field.

How can this be done? What is the equation, or which part number can be modified to change to 40px?
-1.1? .75 , 133%, Looking for some kind of function or math equation using answer below, or any other option which may work.

https://stackoverflow.com/a/54762506/12425844

::ng-deep .mat-form-field-flex > .mat-form-field-infix { padding: 0.4em 0px !important;}
::ng-deep .mat-form-field-label-wrapper { top: -1.5em; }

::ng-deep .mat-form-field-appearance-outline.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label {
    transform: translateY(-1.1em) scale(.75);
    width: 133.33333%;
}


Get this bounty!!!

#StackBounty: #css #reactjs #animation #carousel #react-spring Creating a slider that slides items in an arc / upper cricle

Bounty: 50

I’m attempting to create a carousel that rotates items in a upper circle / arc fashion.
This is how it’s supposed to roll: https://thumbs.gfycat.com/HastyTemptingBarnswallow-mobile.mp4

My initial thought is to have 1 element in the middle then one previous and next which are slightly rotated. Upon dragging it should move all items along the x-axis and slightly rotate. This is my attempt:

https://codesandbox.io/s/muddy-cdn-rbs34?from-embed

Problem is I can’t seem to make the dragging animation very smooth. I might also just be overthinking this and go in the wrong direction. Any advice?


Get this bounty!!!

#StackBounty: #javascript #jquery #html #css Element from fixed to relative on scroll

Bounty: 100

I have made a wrapper in which I have animated the same effect as Apple on their Airpods Pro page. It’s basically a video, when I scroll the video plays bit by bit. The video’s position is fixed so the text nicely scrolls over it. However, the text is only visible when between the offset of a specific division (text-display).

That part works fine. Now I want that when the user has scrolled to the end of the video, and thus the animation is finished, that the video-effect-wrapper goes from a fixed position to a relative position. So that website will scroll it’s content normally after the video-animation.

JSFIDDLE CODE + DEMO

This is an example of what I already tried:

        //If video-animation ended: Make position of video-wrapper relative to continue scrolling
        if ($(window).scrollTop() >= $("#video-effect-wrapper").height()) {
            $(video).css("position", "relative");
            $("#video-effect-wrapper .text").css("display", "none");
        }

This kind of works… But is everything except smooth. And it also needs to be possible to reverse scroll the webpage backwards.

Problems I encountered when trying to fix this problem:

  • The scrolling, and transition from fixed to relative needs to feel natural and smooth
  • The wrapper itself isn’t fixed and contains .text elements, the video is fixed so the .text elements can go over the video element (creating the effect). These .text elements cause problems trying to find a solution


Get this bounty!!!

#StackBounty: #html #css #asp.net-mvc #bootstrap-4 How to change the position of Bootstrap Navigation Bar parent menu item icon at mobi…

Bounty: 50

I am looking for a way to change the position of the bootstrap navigation menu bar parent menu icon, when open in mobile view.

Currently the menu header contains right-arrow-down icon at the end of header name like below.

enter image description here

My requirement is to convert the highlighted right-arrow-down icon to left-arrow icon and change the icon position to start of parent
header menu text and also to change the background color (gray) of parent menu item on mouse hover like below.

enter image description here

below is the navigation menu bar HTML code:

<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav">
    <li class="nav-item" style="background-color: #f5f5f5; height:33px; padding-top:8px;">
        <label class="label d-md-block d-lg-none">Welcome, abc</label>
    </li>
    <li class="nav-item dropdown">
        <a href="#" class="nav-link dropdown-toggle" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">ACCOUNTS</a>
        <div class="dropdown-menu">
            <a class="dropdown-item"><span class="k-icon k-i-plus"></span>New Prospect</a>
            <a class="dropdown-item">Accounts</a>
            <a class="dropdown-item">Prospects</a>
            <a class="dropdown-item">Account Reports</a>
            <a class="dropdown-item">My Account Reports</a>
            <a class="dropdown-item"><span class="k-icon k-i-star"></span> Favorites</a>
        </div>
    </li>
    <li class="nav-item dropdown">
        <a href="#" class="nav-link dropdown-toggle" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">CONTACTS</a>
        <div class="dropdown-menu">
            <a class="dropdown-item">Item 1</a>
            <a class="dropdown-item"><span class="k-icon k-i-star"></span> Favorites</a>
        </div>
    </li>
    <li class="nav-item dropdown">
        <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">LEADS</a>
        <div class="dropdown-menu">         
            <a class="dropdown-item"><span class="k-icon k-i-star"></span> Favorites</a>
        </div>
    </li>
    <li class="nav-item dropdown">
        <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">OPPORTUNITIES</a>
        <div class="dropdown-menu">
            <a class="dropdown-item">Item 1</a>
        </div>
    </li>
    <li class="nav-item dropdown">
        <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">ACTIVITIES</a>
        <div class="dropdown-menu">
            <a class="dropdown-item">Item 1</a>
        </div>
    </li>
</ul>
</div>

It might required to override the existing bootstrap classes to acheive this but I am not sure which class will work for me.
I have tried to look for the ways to acheive this using Bootstrap CSS online but not found any example similar to my requirement. Appreciate your help.


Get this bounty!!!

#StackBounty: #css #angular #angular-material How to add remove button to mat-basic-chip

Bounty: 50

I created a custom styled chips list with mat-basic-chip(Unstyled chips) as per official docs

My Chips look like
enter image description here

Now, I want to add remove buttons to my chips as default mat-chips have
enter image description here

Here is the template of mat-basic-chip

<mat-basic-chip *ngFor="let signal of signals">
                    <div matLine class="text-center">{{signal .name}}</div>
                    <div matLine class="mt-sm-n1 text-center"><small>(Default)</small></div>
</mat-basic-chip>

As per the official docs receives the mat-basic-chip CSS class in addition to the mat-chip class.
So, here is the CSS of .mat-basic-chip to style my custom chips:

.mat-basic-chip {
  display: inline-block;
  clear: right;
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 1vh;
  padding: .7vh 0vh .7vh .7vh;
  margin-right: 2vh;
  margin-top:1vh;
  min-width: 15vh;
 }


Get this bounty!!!

#StackBounty: #css #angular #performance #ag-grid #angular-directive Render additional info in cell when row is hovered in ag-grid

Bounty: 50

I am using angular (^8.2.14) and ag-grid-community (^20.1.0).

I try to achieve the following effect: when the user hovers a specific row, one column shows an additional button which may be clicked.

What does work?
The column with the wanted behaviour gets rendered by a custom cell renderer component which implements the ICellRendererAngularComponent interface. There I can inject the ElementRef and on the lifecycle hook AfterContentChecked I check the parents’ parent for the css-class ‘ag-row-hover’ and if it’s there, I will show this additional button in the renderer component.

custom-cell.component.ts

@Component({
  selector: 'app-custom-cell',
  template: `
      <ng-container *ngIf="hovered; else notHovered">{{form.value * form.value}}
        <button (click)="doStuff(form.value)">show root</button></ng-container>
      <ng-template #notHovered>{{form.value + form.value}}</ng-template>
  `,
})
export class CustomCellComponent implements ICellRendererAngularComp, AfterContentChecked {
  form: FormControl;
  params: ICellRendererParams;
  hovered = false;

  constructor(private elementRef: ElementRef) {
  }

  doStuff(val) {
    alert(val);
  }

  ngAfterContentChecked() {
    this.hovered = (this.elementRef.nativeElement as HTMLElement)
      .parentElement
      .parentElement
      .classList.contains('ag-row-hover');
  }
}

The source code for this is on github

What do I want to improve?
I want to improve the performance and not having explicit checks for this behaviour. I’d rather have a directive with the css-selector ‘.ag-row’, which I can inject to the ICellRendererAngularComponent and then check for the css class ‘.ag-row-hover’ on every check. Or have a directive with the css-selector ‘.ag-row-hover’ which is there, or is not. Anyone has any ideas how to improve my existing solution?


Get this bounty!!!

#StackBounty: #css #angular How to get shuffling css animation to work in Angular8? (similar code works with angular2)

Bounty: 50

I have a app-transition-group component that I want to animate. In my css, I have:

.flip-list-move {
  transition: transform 1s;
}

Though it appears when shuffle is called, it always changes instantaneously and never animates with angular8. It works in angular2. What is the issue?

My code is this:

app.component.ts

@Component({
  selector: 'my-app',
  template: `
    <h2>Items reorder/shuffle animations with Angular8 ngFor</h2>
    <button (click)="shuffle()">Configure</button>
    <ul [transition-group]="'flip-list'">
      <li *ngFor="let item of items" transition-group-item>
        {{ item }}
      </li>
    </ul>
  `,
})
export class App {
  items = [1, 2, 3, 4, 5, 6, 7, 8, 9];

  shuffle() {
    this.items = this.shufflestuff(this.items)
  }
}

shufflestuff=function(array) {
  const length = array == null ? 0 : array.length
  if (!length) {
    return []
  }
  let index = -1
  const lastIndex = length - 1
  const result = this.copyArray(array)
  while (++index < length) {
    const rand = index + Math.floor(Math.random() * (lastIndex - index + 1))
    const value = result[rand]
    result[rand] = result[index]
    result[index] = value
  }
  return result
}

copyArray=function(source, array) {
  let index = -1
  const length = source.length

  array || (array = new Array(length))
  while (++index < length) {
    array[index] = source[index]
  }
  return array
}

I have modules imported, and in my transition-group.ts file I have:

import { Component, ContentChildren, Directive, ElementRef, Input, QueryList } from ‘@angular/core’;

@Directive({
  selector: '[app-transition-group-item]'
})
export class TransitionGroupItemDirective {
  prevPos: any;
  newPos: any;
  el: HTMLElement;
  moved: boolean;
  moveCallback: any;

  constructor(elRef: ElementRef) {
    this.el = elRef.nativeElement;
  }
}

@Directive({
  selector: '[app-transition-group]'
})
export class TransitionGroupComponent {
  @Input('app-transition-group') class;

  @ContentChildren(TransitionGroupItemDirective) items: QueryList<TransitionGroupItemDirective>;

  ngAfterContentInit() {
    this.refreshPosition('prevPos');
    this.items.changes.subscribe(items => {
      items.forEach(item => {
        item.prevPos = item.newPos || item.prevPos;
      });

      items.forEach(this.runCallback);
      this.refreshPosition('newPos');
      items.forEach(this.applyTranslation);

      // force reflow to put everything in position
      const offSet = document.body.offsetHeight;
      this.items.forEach(this.runTransition.bind(this));
    })
  }

  runCallback(item: TransitionGroupItemDirective) {
    if(item.moveCallback) {
      item.moveCallback();
    }
  }

  runTransition(item: TransitionGroupItemDirective) {
    if (!item.moved) {
      return;
    }
    const cssClass = this.class + '-move';
    let el = item.el;
    let style: any = el.style;
    el.classList.add(cssClass);
    style.transform = style.WebkitTransform = style.transitionDuration = '';
    el.addEventListener('transitionend', item.moveCallback = (e: any) => {
      if (!e || /transform$/.test(e.propertyName)) {
        el.removeEventListener('transitionend', item.moveCallback);
        item.moveCallback = null;
        el.classList.remove(cssClass);
      }
    });
  }

  refreshPosition(prop: string) {
    this.items.forEach(item => {
      item[prop] = item.el.getBoundingClientRect();
    });
  }

  applyTranslation(item: TransitionGroupItemDirective) {
    item.moved = false;
    const dx = item.prevPos.left - item.newPos.left;
    const dy = item.prevPos.top - item.newPos.top;
    if (dx || dy) {
      item.moved = true;
      let style: any = item.el.style;
      style.transform = style.WebkitTransform = 'translate(' + dx + 'px,' + dy + 'px)';
      style.transitionDuration = '0s';
    }
  }
}

How can I get this to animate when the button is hit? Stackblitz here with Angular8: https://stackblitz.com/edit/angular-so-1-t81c8l?file=src/app/app.component.css

The working version in Angular 2 is here at this plunkr:
https://next.plnkr.co/edit/i2hRcrTHLxTKA7mk

The only difference between the angular8 and the angular2 version is the app-transition-group/transition-group is an @Component in angular2 instead of an @Directive in angular8. If there is a better way to do this, am open to suggestions.


Get this bounty!!!