使用 padding-bottom 宽高比 hack 强制图像保持 ::before 的尺寸
Force image to maintain dimensions of ::before with padding-bottom aspect ratio hack
我正在使用 ::before
和 content: ''; padding-bottom: 100%
技巧来尝试在图像上强制执行 1:1 纵横比。我还添加了 overflow: hidden
。但是,正如您从屏幕截图中看到的那样,图像溢出到我在 ::before
中创建的正方形之外。我根本不希望图像拉伸,所以所有图像都应用了 object-fit: contain
。
我在纵横比方面遵循 various threads and a CSS Tricks article。
我怎样才能确保图像整齐地适合那个方块并且根本不会溢出?
编辑:Code sandbox
代码如下:
Item.tsx
<StyledItemWrapper
className={item.animation}
onClick={() => {
clickItem(item);
}}
>
<picture>
<img src={item.image} alt={item.title} />
</picture>
<StyledItemInfo>
<p>{item.title}</p>
<p>{item.description}</p>
<p>${item.price.toFixed(2)}</p>
</StyledItemInfo>
<Button onClick={() => handleAddToCart(item)}>Add To Cart</Button>
</StyledItemWrapper>
Item.styles.ts
export const StyledItemWrapper = styled.div`
display: flex;
justify-content: space-between;
flex-direction: column;
position: relative;
border: 1px solid lightblue;
border-radius: 20px;
&::before {
display: block;
overflow: hidden;
padding-bottom: 100%;
content: "";
}
picture {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
max-height: 50%;
img {
border-radius: 20px 20px 0 0;
width: 100%;
height: 100%;
object-fit: contain;
}
}
button {
border-radius: 0 0 20px 20px;
}
`;
export const StyledItemInfo = styled.div`
font-family: Arial, Helvetica, sans-serif;
padding: 1rem;
height: 100%;
`;
问题是我对 StyledItemWrapper
应用了样式,它包裹了整张卡片而不仅仅是图像,所以任何填充等都会影响整个卡片的布局。
宽高比的填充和伪选择器 hack 仅在将其应用于专用图像容器 时才有效。所以,这就是我所做的:
Item.tsx
const Item: React.FC<Props> = ({ item, handleAddToCart, clickItem }) => (
<StyledItemWrapper
className={item.animation}
onClick={() => {
clickItem(item);
}}
>
<StyledVisualWrapper> // new styled component
<picture>
<img src={item.image} alt={item.title} />
</picture>
</StyledVisualWrapper>
<StyledItemInfo>
<p>{item.title}</p>
<p>{item.description}</p>
<p>${item.price.toFixed(2)}</p>
</StyledItemInfo>
<Button onClick={() => handleAddToCart(item)}>Add To Cart</Button>
</StyledItemWrapper>
);
Item.styles.ts
export const StyledItemWrapper = styled.div`
display: flex;
justify-content: space-between;
flex-direction: column;
border: 1px solid lightblue;
border-radius: 20px;
button {
border-radius: 0 0 20px 20px;
}
`;
export const StyledVisualWrapper = styled.div`
position: relative; // move from StyledItemWrapper to here
max-height: 50%;
&::before {
display: block;
overflow: hidden;
padding-bottom: 100%;
content: "";
}
picture {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
img {
border-radius: 20px 20px 0 0;
width: 100%;
height: 100%;
object-fit: contain;
}
}
`;
我正在使用 ::before
和 content: ''; padding-bottom: 100%
技巧来尝试在图像上强制执行 1:1 纵横比。我还添加了 overflow: hidden
。但是,正如您从屏幕截图中看到的那样,图像溢出到我在 ::before
中创建的正方形之外。我根本不希望图像拉伸,所以所有图像都应用了 object-fit: contain
。
我在纵横比方面遵循 various threads and a CSS Tricks article。
我怎样才能确保图像整齐地适合那个方块并且根本不会溢出?
编辑:Code sandbox
代码如下:
Item.tsx
<StyledItemWrapper
className={item.animation}
onClick={() => {
clickItem(item);
}}
>
<picture>
<img src={item.image} alt={item.title} />
</picture>
<StyledItemInfo>
<p>{item.title}</p>
<p>{item.description}</p>
<p>${item.price.toFixed(2)}</p>
</StyledItemInfo>
<Button onClick={() => handleAddToCart(item)}>Add To Cart</Button>
</StyledItemWrapper>
Item.styles.ts
export const StyledItemWrapper = styled.div`
display: flex;
justify-content: space-between;
flex-direction: column;
position: relative;
border: 1px solid lightblue;
border-radius: 20px;
&::before {
display: block;
overflow: hidden;
padding-bottom: 100%;
content: "";
}
picture {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
max-height: 50%;
img {
border-radius: 20px 20px 0 0;
width: 100%;
height: 100%;
object-fit: contain;
}
}
button {
border-radius: 0 0 20px 20px;
}
`;
export const StyledItemInfo = styled.div`
font-family: Arial, Helvetica, sans-serif;
padding: 1rem;
height: 100%;
`;
问题是我对 StyledItemWrapper
应用了样式,它包裹了整张卡片而不仅仅是图像,所以任何填充等都会影响整个卡片的布局。
宽高比的填充和伪选择器 hack 仅在将其应用于专用图像容器 时才有效。所以,这就是我所做的:
Item.tsx
const Item: React.FC<Props> = ({ item, handleAddToCart, clickItem }) => (
<StyledItemWrapper
className={item.animation}
onClick={() => {
clickItem(item);
}}
>
<StyledVisualWrapper> // new styled component
<picture>
<img src={item.image} alt={item.title} />
</picture>
</StyledVisualWrapper>
<StyledItemInfo>
<p>{item.title}</p>
<p>{item.description}</p>
<p>${item.price.toFixed(2)}</p>
</StyledItemInfo>
<Button onClick={() => handleAddToCart(item)}>Add To Cart</Button>
</StyledItemWrapper>
);
Item.styles.ts
export const StyledItemWrapper = styled.div`
display: flex;
justify-content: space-between;
flex-direction: column;
border: 1px solid lightblue;
border-radius: 20px;
button {
border-radius: 0 0 20px 20px;
}
`;
export const StyledVisualWrapper = styled.div`
position: relative; // move from StyledItemWrapper to here
max-height: 50%;
&::before {
display: block;
overflow: hidden;
padding-bottom: 100%;
content: "";
}
picture {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
img {
border-radius: 20px 20px 0 0;
width: 100%;
height: 100%;
object-fit: contain;
}
}
`;