CSS實現自適應左側選單

.

先看效果圖

效果圖

選單需要的資料結構

[{
    name: 'xxx0',
    children: [
      {
        name: "xxx01"
      }
    ],
  }, {
    name: 'xxx1',
    children: [],
}]

實現程式碼js(react)

import React from 'react'
import PropTypes from 'prop-types'

import styles from "./MenuNow.less"

class Menu extends React.Component {

  static propTypes = {
    navOpenKeys: PropTypes.array,
    changeOpenKeys: PropTypes.func,
    location: PropTypes.object,
    menu: PropTypes.array.isRequired
  }

  render() {
    const {
      menu: data = [],
      location = {},
      navOpenKeys = () => {},
      changeOpenKeys = () => {},
    } = this.props;
      // 遞迴生成選單
      const getItems = (data) => {
        if(!data.length) {
          return <div className="menu-list">
            <a style={{ color: "rgb(125, 00, 00)"}}>
              ( ⊙ o ⊙ )null</a>
          </div>
        }
        return data.map((item, index) => {
          if (item.children) {
            let isOpenThis = navOpenKeys.some(value => item.uuid == value);
            return (
              <div
                key={item.uuid}
                className={ "menu-wrapper" + (isOpenThis ? 
                " menu-wrapper-active" : "") }
              >
                <span
                  style={{ top: index * 44 }}
                  onClick={
                    () => {
                      let newNavOpenKeys = [...navOpenKeys];
                      let findIndex = newNavOpenKeys.findIndex(
						value => value == item.uuid)
                      if(findIndex > -1) {
                        newNavOpenKeys.splice(findIndex, 1);
                        return changeOpenKeys(newNavOpenKeys);
                      }
                      newNavOpenKeys.push(item.uuid + "");
                      changeOpenKeys(newNavOpenKeys);
                    }
                  }
                >
                  {item.name}
                  <span 
                  	style={
                  		{
                  			 transform: isOpenThis ?  
                  				"" : "rotate(180deg)" 
                  		}
                  	}></span>
                </span>
                <div className="menu-all-wrapper" style={{}} >
                  <div style={{
                    height: isOpenThis ? "auto" : 0,
                    opacity: isOpenThis ? "1" : 0,
                  }}>
                    {getItems(item.children)}
                  </div>
                </div>
              </div>
            )
          }
          return (
            <div key={item.cname}
              className={ "menu-list " + (name == item.name ? 
              "menu-list-active" : "") }
            >
              <Link to={item.route || '#'} >
                {item.icon && <Icon type={item.icon} />}
                {item.cname}
              </Link>
            </div>
          )
        })
      }
      const menuItems = getItems(data);

      return (
        <div className={styles.menu_auto}>
          {menuItems}
        </div>
      )
  }
};

export default Menu

css部分

.menu_auto {
  height: 100%;
  position: relative;
  :global {
    .menu-wrapper {
      margin-top: 4px;
      max-height: calc(~"100% - 48px");
      overflow: auto;
      &.menu-wrapper-active {
        > span {
          position: absolute;
          top: 0px;
        }
        .menu-all-wrapper {
          padding-top: 48px;
        }
      }
      &::-webkit-scrollbar {
        width: 2px;
        background-color: transparent;
      }
      &::-webkit-scrollbar-thumb {
        border-top: 40px solid rgba(74, 144, 226, 0.56);
        background-color: #fff;
      }
      > span {
        width: 100%;
        text-align: center;
        display: block;
        white-space: normal;
        background-color: #7dace3;
        color: #fff;
        line-height: 40px;
        height: 40px;
        cursor: pointer;
        > span {
          display: inline-block;
          transition: transform 300ms,
        }
      }
      .menu-all-wrapper {
        overflow: hidden;
        height: inherit;
        > div {
          transition: opacity 0.6s,
        }
      }

    }
    .menu-list {
      overflow: hidden;
      &.menu-list-active {
        > a {
          background: #fff;
          color: #000;
        }
      }
      a {
        text-align: center;
        color: #fff;
        font-family: PingFangSC-Regular;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        padding: 0 8px;
        line-height: 40px;
        height: 40px;
        cursor: pointer;
        display: block;
        &:hover {
          background: #fff;
          color: #000;
        }
      }
    }

  }
}

總結

滾動條竟然可以有border,神奇

&::-webkit-scrollbar {
  width: 2px;
  background-color: transparent;
}
&::-webkit-scrollbar-thumb {
  border-top: 40px solid rgba(74, 144, 226, 0.56);
  background-color: #fff;
}

thanks