简体   繁体   中英

What is Google search result page Carousel technologies?

In the last few weeks Google show a carousel for Stack Overflow result, It's awesome and move smooth but weird for me, there is no JavaScript DOM changing and even CSS that cause to horizontal scroll, I cannot find it out.

Stack Overflow 的 Google SERP 轮播

Even I read about CSS Horizontal Scroll but it is so different and it is just for Google Chrome in other browsers it doesn't exist.

After some searches and experiments I found out this weird carousel is actually a long horizontal division with display: none scroll bar, but how with grab and moving mouse pointer, the division scroll moving? is that a native chrome trick? or just use JavaScript to calculate the motion of horizontal scroll?

Actually, I have found the answer to my question, but I decided to post it here now. Google website developers use many sexy tricks to implement the UI and this carousel is one of them, definitely, this is not DOM manipulation, it's a simple scrolled division . Because of this, the division moves very smoothly and even with dragging move properly.

A scroll has some native behavior in some devices like Apple devices or other touch devices, even Microsoft new laptops have some features about scrolling by touch. but if we use a few JavaScript codes to handle dragging it will be nice, see following code:

HINT : You can use your native device horizontal scrolling features like the two-finger horizontal scroll on MacBook trackpad OR using click and drag to move the carousel horizontally

 var slider = document.querySelector('.items'); var isDown = false; var startX; var scrollLeft; slider.addEventListener('mousedown', function (e) { isDown = true; slider.classList.add('active'); startX = e.pageX - slider.offsetLeft; scrollLeft = slider.scrollLeft; }); slider.addEventListener('mouseleave', function () { isDown = false; slider.classList.remove('active'); }); slider.addEventListener('mouseup', function () { isDown = false; slider.classList.remove('active'); }); slider.addEventListener('mousemove', function (e) { if (!isDown) return; e.preventDefault(); var x = e.pageX - slider.offsetLeft; var walk = (x - startX) * 3; //scroll-fast slider.scrollLeft = scrollLeft - walk; });
 @import url(https://fonts.googleapis.com/css?family=Rubik); body, html { color: #fff; text-align: center; background: #efefef; font-family: Helvetica, sans-serif; margin: 0; } .grid-container { background: #efefef; font-family: 'Rubik', sans-serif; } @supports (display: grid) { .grid-container { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: auto 1fr auto; grid-template-areas: "header header header" "title title footer" "main main main"; } @media screen and (max-width: 500px) { .grid-container { grid-template-columns: 1fr; grid-template-rows: 0.3fr 1fr auto 1fr; grid-template-areas: "header" "title" "main" "footer"; } } .grid-item { color: #fff; background: skyblue; padding: 3.5em 1em; font-size: 1em; font-weight: 700; } .header { background-color: #092a37; grid-area: header; padding: 1em; } .title { color: #555; background-color: #f4fbfd; grid-area: title; } .main { color: #959595; background-color: white; grid-area: main; padding: 0; overflow-x: scroll; overflow-y: hidden; } .footer { background-color: #5bbce4; grid-area: footer; padding: 0.6em; } .items { position: relative; width: 100%; overflow-x: scroll; overflow-y: hidden; white-space: nowrap; transition: all 0.2s; transform: scale(0.98); will-change: transform; user-select: none; cursor: pointer; } .items.active { background: rgba(255, 255, 255, 0.3); cursor: grabbing; cursor: -webkit-grabbing; transform: scale(1); } .item { display: inline-block; background: skyblue; min-height: 100px; min-width: 400px; margin: 2em 1em; } @media screen and (max-width: 500px) { .item { min-height: 100px; min-width: 200px; } } } a { display: block; color: #c9e9f6; text-decoration: underline; margin: 1em auto; } a:hover { cursor: pointer; } p { text-align: left; text-indent: 20px; font-weight: 100; } i { color: skyblue; }
 <div class="grid-container"> <main class="grid-item main"> <div class="items"> <div class="item item1"></div> <div class="item item2"></div> <div class="item item3"></div> <div class="item item4"></div> <div class="item item5"></div> <div class="item item6"></div> <div class="item item7"></div> <div class="item item8"></div> <div class="item item9"></div> <div class="item item10"></div> </div> </main> </div>

For ReactJs developer I created a good hook for supporting horizontal scroll in desktop:

import { useEffect } from 'react';
import type { MutableRefObject } from 'react';

const useHorizontalScroll = (
  scrollWrapperRef: MutableRefObject<HTMLElement>,
  scrollSpeed = 1
): void => {
  useEffect(() => {
    const horizWrapper = scrollWrapperRef.current;
    let isDown = false;
    let startX: number;
    let scrollLeft: number;
    horizWrapper?.addEventListener('mousedown', (e: any) => {
      isDown = true;
      startX = e.pageX - horizWrapper?.offsetLeft;
      scrollLeft = horizWrapper?.scrollLeft;
    });
    horizWrapper?.addEventListener('mouseleave', () => {
      isDown = false;
    });
    horizWrapper?.addEventListener('mouseup', () => {
      isDown = false;
    });
    horizWrapper?.addEventListener('mousemove', (e: any) => {
      if (!isDown) return;
      e.preventDefault();
      const x = e.pageX - horizWrapper?.offsetLeft;
      const walk = (x - startX) * scrollSpeed;

      horizWrapper.scrollLeft = scrollLeft - walk;
    });
  }, [scrollSpeed, scrollWrapperRef]);
};

export default useHorizontalScroll;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM