代码之家  ›  专栏  ›  技术社区  ›  Adam Olsson

在中心CSS中对齐单个列表项

  •  0
  • Adam Olsson  · 技术社区  · 7 年前

    我正在Reactjs中创建一个包含四个元素的导航栏。这些项目是一个简单的无序列表,一些css使用flexbox将它们水平对齐。

    <ul>
        <li>One</li>
        <li>Two</li>
        <li>Three</li>
        <li>Four</li>
    <ul/>
    

    我想要实现的是:当选择列表项时,将所选列表项与中心对齐。我添加了一张专业图片以供澄清。稍后将为该更改设置动画以实现平滑过渡,如旋转木马。

    The selected item appear in the center row

    以下是的css <ul> 标签

    ul {
        list-style-type: none;
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        justify-content: center;
    }
    

    我尝试的是使用 align-self: center <li> 物品,但没有运气。

    有没有人有做类似事情的经验?我对所有类型的解决方案都持开放态度,即使是那些不使用flexbox的解决方案。

    非常感谢。

    3 回复  |  直到 7 年前
        1
  •  2
  •   haugsand    7 年前

    列表元素是否有固定的with,您知道有多少项吗?如果是这样,您可以计算列表的中心、项目偏移量,并添加CSS转换。

    示例:

    • 您有一个包含四项的列表。
    • 每个项目的宽度等于100px。
    • 因此,列表的总宽度为400px。
    • 列表的中心点是从左侧开始的200px。
    • 第二项的中心点是从左侧开始的150px。因此,我们必须从左侧移动列表200px-150px=50px。
    • 第四项的中心点是从左侧开始的350px。因此,我们必须将列表从左边移到200px-350px=-150px。

    如果您的列表在列表长度和项目宽度方面都是动态的,那么您可以使用 Element.getBoundingClientRect() 找到元素的尺寸,并使用与上述相同的计算。

    代码笔: https://codepen.io/anon/pen/vjJMVL

    HTML:

    <ul class="selected-2">
      <li>1</li>
      <li class="selected">2</li>
      <li>3</li>
      <li>4</li>
    </ul>
    
    <ul class="selected-4">
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li class="selected">4</li>
    </ul>
    

    CSS:

    ul {
      display: flex;
      justify-content: center;
      list-style: none;
    }
    
    li {
      width: 80px;
      height: 80px;
      background-color: #eee;
      margin: 10px;
    }
    
    .selected {
      background-color: #ccc;
    }
    
    .selected-2 {
      transform: translateX(50px)  
    }
    
    .selected-4 {
      transform: translateX(-150px)  
    }
    
        2
  •  1
  •   Ori Drori    7 年前

    计算单击的 <MenuItem> 通过使用居中 Element.getBoundingClientRect() 要得到它 left width ,并将其传递给父级( <Menu> )。在父级中,使用 <ul> s参考号获取 左边 和宽度 要素getBoundingClientRect() .计算 moveTo 状态,并更新 <ul> s样式 transform: translateX() 因此:

    const { Component } = React;
    const items = ['One', 'Two', 'Three', 'Four'];
    
    class MenuItem extends Component {
      clickHandler = (e) => {
        const { left, width } = e.target.getBoundingClientRect();
        const itemCenter = left + width / 2;
        this.props.updateCenter(itemCenter);
      }
    
      render() {
        const { children } = this.props;
        
        return (
          <li onClick={this.clickHandler}>{children}</li>
        );
      }
    }
    
    class Menu extends Component {
      state = {
        moveTo: 0
      };
      
      updateCenter = (itemCenter) => {
        const { left, width } = this.ul.getBoundingClientRect();
        
        //this.ul.style.transform = `translateX(${center}px)`;
        
        this.setState(() => ({
          moveTo: left + width / 2 - itemCenter
        }));
      };
    
      render() {
        const { items } = this.props;
        const { moveTo } = this.state;
        
        return (
          <nav>
            <ul ref={(ul) => this.ul = ul} style={{
              transform: `translateX(${moveTo}px)`
            }}>
            {
              items.map((text) => (
                <MenuItem key={text} 
                  updateCenter={this.updateCenter}>
                  {text}
                </MenuItem>
              ))
            }
            </ul>
          </nav>
        );
      }
    }
    
    ReactDOM.render(
      <Menu items={items} />,
      demo
    );
    /** demo only - display the center **/
    body::before {
      position: absolute;
      left: 50%;
      height: 100vh;
      border-right: 1px solid black;
      content: '';
    }
    
    nav {
      overflow: hidden;
    }
    
    ul {
      list-style-type: none;
      display: flex;
      flex-direction: row;
      flex-wrap: nowrap;
      justify-content: center;
      transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    }
    
    li {
      padding: 1em;
      border: 1px solid black;
      cursor: pointer;
    }
    
    ul li:not(:last-child) {
      margin: 0 1em 0 0;
    }
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    
    <div id="demo"></div>
        3
  •  0
  •   Rainbow    7 年前

    由于我没有完全得到你想要的,这是我能想到的最好的方法,对所选的一个应用绝对定位,并用z索引将其与其他重叠

    document.querySelectorAll('li').forEach(function(li){
    	li.addEventListener('click',function(e){
    		document.querySelectorAll('li').forEach(function(obj){
    			obj.classList.remove('selected');
    		});
    		e.target.classList.add("selected");		
    	});
    });
    ul {
        list-style-type: none;
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        justify-content: center;
    }
    
    
    li{
        border:1px solid;
        padding:10px;
        cursor:pointer;
        position:relative;
        transition:all ease 1s;
        margin:0 20px;
    }
    
    
    .selected{
        transform:scale(2.1);
        background:white;
        box-shadow:0px 0px 55px black;
        position:absolute;
        z-index:5;
    }
    <ul>
        <li>One</li>
        <li>Two</li>
        <li>Three</li>
        <li>Four</li>
    </ul>