重叠头像:SCSS转CSS、PUG转HTML及悬停/间距问题修复
重叠头像效果的问题解决指南
我来帮你解决这几个问题,一步步拆解:
一、PUG转HTML、SCSS转CSS的基础方法
PUG转HTML:PUG是依赖缩进的模板语言,转成HTML就是把缩进结构换成对应的标签嵌套。比如你参考的PUG如果是:
ul.c-profile__list li.c-profile(data-name='Tobias') li.c-profile(data-name='Lindsey')转成HTML就是:
<ul class="c-profile__list"> <li class="c-profile" data-name="Tobias"></li> <li class="c-profile" data-name="Lindsey"></li> </ul>你用React的话,JSX写法和HTML基本一致,只要把
class换成className,属性用驼峰或字符串格式即可。SCSS转CSS:SCSS的嵌套语法要展开成普通CSS,比如SCSS里的:
.c-profile { &:hover { transform: scale(1.2); &:after { content: attr(data-name); // 其他样式 } } }转成CSS就是:
.c-profile:hover { transform: scale(1.2); } .c-profile:hover:after { content: attr(data-name); // 其他样式 }你现在提供的CSS其实已经是转好的原生CSS了,这部分没问题。
二、解决你遇到的两个具体问题
1. 头像之间间距过大的问题
你的代码里犯了一个结构错误:每个Todo组件都渲染了一个单独的<ul class="c-profile__list">,而不是把所有头像的<li>放在同一个<ul>里。这样每个ul都会自带默认间距,而且flex布局也完全失效了。
修正方法:在App组件里只渲染一个<ul class="c-profile__list">,然后把所有Todo的<li>嵌套在这个ul内部。
2. 鼠标悬停时名称无法显示的问题
这个问题有两个核心原因:
- React的内联样式不支持伪元素(比如
:after),也不支持SCSS的嵌套语法(像&:hover&:after这种写法完全无效); - 你在CSS里用了
content: attr(username),但你的<li>元素上根本没有username属性,而且内联样式里的content:attr(${name})``写法错误,React内联样式不能设置content属性。
修正方法:
- 给每个
<li>添加data-name属性,把用户名存进去; - 把伪元素的样式全部写在CSS里,不要用内联样式;
- 移除Todo组件里无效的内联样式
profile。
三、修正后的完整代码
React组件代码
import React from 'react'; import { render } from 'react-dom'; import './style.css'; class App extends React.Component { constructor() { super(); this.state = { todos: [ {name:'Tobias', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/7/77/2x01_The_One_Where_Michael_Leaves_%28098%29.png/revision/latest?cb=20121126025806'}, {name:'Lindsey', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/1/16/Season_3_Character_Promos_-_Lindsay_Bluth_F%C3%BCnke_01.jpg/revision/latest?cb=20111027201233'}, {name:'Buster', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/b/be/Season_3_Character_Promos_-_Buster_Bluth_01.jpg/revision/latest?cb=20111027201440'}, {name:'George Michael', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/c/c3/Season_1_Character_Promos_-_George_Michael_Bluth_02.jpeg/revision/latest?cb=20120429230332'}, {name:'Gob', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/0/02/Season_1_Character_Promos_-_G.O.B.jpeg/revision/latest?cb=20120429230530'}, {name:'Michael', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/1/10/1x01_Pilot_%2839%29.png/revision/latest?cb=20120301050056'} ], }; } render() { return ( <div> <ul className="c-profile__list"> {this.state.todos.map((todo, index) => ( <Todo key={index} todo={todo} /> ))} </ul> </div> ); } } class Todo extends React.Component { render() { const { name, avatar } = this.props.todo; return ( <li className="c-profile" style={{backgroundImage: `url(${avatar})`}} data-name={name} ></li> ); } } render(<App />, document.getElementById('root'));
CSS代码(修正了伪元素和定位问题)
html { box-sizing: border-box; } *, *:before, *:after { box-sizing: inherit; } html, body { width: 100%; height: 100%; } body { display: flex; align-items: center; justify-content: center; font-family: system-ui; flex-direction: column; color: #2c2c54; font-size: 1.6rem; } .c-profile { width: 70px; height: 70px; border: 4px solid white; border-radius: 50%; box-shadow: 0px 3px 8px rgba(44, 44, 84, .2); display: inline-block; background: white; cursor: pointer; background-size: cover; background-position: center center; transition: all 200ms ease; position: relative; /* 新增:让伪元素相对于li定位 */ } .c-profile:nth-of-type(n+2) { margin-left: -42px; } .c-profile:hover { transform: scale(1.2); box-shadow: 0px 8px 20px rgba(44, 44, 84, .2); z-index: 10; /* 新增:让hover的头像在最上层,避免被遮挡 */ } .c-profile:hover:after { position: absolute; content: attr(data-name); /* 改成读取data-name属性 */ background: rgba(255, 255, 255, .95); color: inherit; font-size: 10px; padding: 4px; width: auto; bottom: -0.5rem; right: -0.5rem; box-shadow: 0px 5px 12px rgba(0, 0, 0, .12); opacity: 0; border-radius: 0.15rem; animation: fade 100ms ease 750ms forwards; white-space: nowrap; /* 新增:防止用户名换行 */ } .c-profile__list { display: flex; position: relative; width: auto; padding-top: 1rem; padding-bottom: 1rem; list-style: none; /* 统一移除ul默认样式 */ } .c-profile__list:hover .c-profile:nth-of-type(n+2) { margin-left: 7px; } article { width: 100%; max-width: 600px; } @keyframes fade { from { opacity: 0; } to { opacity: 1; } }
这样调整后,头像的重叠间距会恢复正常,鼠标悬停时也能正确显示用户名了。
内容的提问来源于stack exchange,提问作者Umbro
相关产品推荐
相关产品推荐

