如何用Material Design实现页面右侧固定悬浮div并修复卡片布局
修复Angular Material中悬浮卡片压缩左侧内容的布局问题
问题描述
我正在尝试创建一个包含卡片的页面布局,右侧设置一个摘要卡片,使其在页面滚动时保持固定悬浮(类似Bootstrap的affix组件)。目前我的实现存在问题:左侧的三张卡片会将该悬浮卡片视为所在行的一部分,导致自身尺寸被压缩,但滚动时悬浮功能正常。
效果截图
- 布局异常截图:[左侧卡片被压缩,右侧悬浮卡片占据行空间]
- 滚动悬浮正常截图:[滚动时右侧卡片保持固定悬浮]
当前代码
<div class="container" layout="row" layout-xs="column"> <div flex="20" hide-sm></div> <div flex> <h1 style="margin-bottom: 20px">Which edition?</h1> </div> <div flex="20" hide-sm></div> </div> <div sticky style="position: relative; float: right; z-index: 2;" flex="20"> <div> <md-card ng-class="vm.selectedSupport === 'standard' ? 'card-3' : 'card-1'" ng-click="vm.toggleSelectedSupport('standard')"> <img src="images/priority_bw.jpg" class="md-card-image" alt="Washed Out" ng-if="vm.selectedSupport !== 'standard'"> <img src="images/priority.jpg" class="md-card-image" alt="Washed Out" ng-if="vm.selectedSupport === 'standard'"> <md-card-title layout="column" layout-align="center center"> <md-card-title-text> <span class="md-headline">I don't need priority support</span> </md-card-title-text> </md-card-title> <md-card-content layout="column" layout-align="center center"> <p align="center"> over email only <br/> within three working days </p> <h2>$0</h2> </md-card-content> <md-card-actions layout="column" layout-align="start"> <md-button ng-class="vm.selectedSupport === 'standard' ? 'md-raised md-primary md-hue-1' : 'md-raised md-accent md-hue-1'"> Selected </md-button> </md-card-actions> </md-card> </div> </div> <div class="container" layout="row" layout-xs="column"> <div flex="20" hide-sm></div> <div flex> <md-card ng-class="vm.selectedCard === 'card1' ? 'card-3' : 'card-1'" ng-click="vm.toggleSelected('card1')"> <img src="images/header_bw.jpg" class="md-card-image" alt="Washed Out" ng-if="vm.selectedCard !== 'card1'"> <img src="images/header.jpg" class="md-card-image" alt="Washed Out" ng-if="vm.selectedCard === 'card1'"> <md-card-title layout="column" layout-align="center center"> <md-card-title-text> <span class="md-headline">Free</span> </md-card-title-text> </md-card-title> <md-card-content layout="column" layout-align="center center"> <p align="center"> This is the free version of the software that we are offering. It's not the full offering so if you want more i will need to see some $$$.</p> <p> Some tool 1 <br/> Some tool 1 <br/> Some tool 1 <br/> </p> <h2>Free</h2> </md-card-content> <md-card-actions layout="column" layout-align="start"> <md-button ng-class="vm.selectedCard === 'card1' ? 'md-raised md-primary md-hue-1' : 'md-raised md-accent md-hue-1'"> Selected </md-button> </md-card-actions> </md-card> </div> <div flex> <md-card ng-class="vm.selectedCard === 'card2' ? 'card-3' : 'card-1'" ng-click="vm.toggleSelected('card2')"> <img src="images/header1_bw.jpg" class="md-card-image" alt="Washed Out" ng-if="vm.selectedCard !== 'card2'"> <img src="images/header1.jpg" class="md-card-image" alt="Washed Out" ng-if="vm.selectedCard === 'card2'"> <md-card-title layout="column" layout-align="center center"> <md-card-title-text> <span class="md-headline">Pro</span> </md-card-title-text> </md-card-title> <md-card-content layout="column" layout-align="center center"> <p align="center"> This is the free version of the software that we are offering. It's not the full offering so if you want more i will need to see some $$$.</p> <p> Some tool 1 <br/> Some tool 1 <br/> Some tool 1 <br/> </p> <h2>$9.99/month</h2> </md-card-content> <md-card-actions layout="column" layout-align="start"> <md-button ng-class="vm.selectedCard === 'card2' ? 'md-raised md-primary md-hue-1' : 'md-raised md-accent md-hue-1'"> Selected </md-button> </md-card-actions> </md-card> </div> <div flex> <md-card ng-class="vm.selectedCard === 'card3' ? 'card-3' : 'card-1'" ng-click="vm.toggleSelected('card3')"> <img src="images/header2_bw.jpg" class="md-card-image" alt="Washed Out" ng-if="vm.selectedCard !== 'card3'"> <img src="images/header2.jpg" class="md-card-image" alt="Washed Out" ng-if="vm.selectedCard === 'card3'"> </md-card> </div> </div>
问题原因
你现在的问题根源在于:悬浮卡片虽然加了float:right,但它还是和左侧的卡片布局处于同一个文档流里。Angular Material的layout="row"会把同一层级的所有元素都算进布局宽度里,所以左侧的三个flex容器就被迫压缩自己的宽度,来给右侧的悬浮卡片腾地方。
修复方案
咱们得把悬浮卡片从文档流里“拎出来”,让它不参与左侧布局的宽度计算,同时还要保留滚动时固定的功能。这里给你两个靠谱的方案:
方案1:用position: sticky+容器嵌套
把悬浮卡片放到一个主容器里,给主容器设置相对定位,然后把悬浮卡片固定在右侧,同时给左侧内容加个右边距,避免被悬浮卡片挡住:
<!-- 主容器设为相对定位,作为悬浮卡片的参考 --> <div class="main-container" style="position: relative; max-width: 1200px; margin: 0 auto;"> <!-- 顶部标题栏 --> <div class="container" layout="row" layout-xs="column"> <div flex="20" hide-sm></div> <div flex> <h1 style="margin-bottom: 20px">Which edition?</h1> </div> <div flex="20" hide-sm></div> </div> <!-- 左侧内容区:加margin-right给悬浮卡片留位置 --> <div class="content-wrapper" style="margin-right: 22%;"> <div class="container" layout="row" layout-xs="column"> <div flex="20" hide-sm></div> <div flex> <!-- 第一张卡片代码不变 --> </div> <div flex> <!-- 第二张卡片代码不变 --> </div> <div flex> <!-- 第三张卡片代码不变 --> </div> </div> </div> <!-- 悬浮卡片:用sticky固定,top设成你想要的距离顶部的位置 --> <div sticky style="position: sticky; top: 20px; right: 10%; width: 20%; z-index: 2;"> <!-- 悬浮卡片内容不变 --> </div> </div>
方案2:Angular Material布局嵌套+绝对定位
利用Angular Material的布局系统,把左侧内容和右侧悬浮卡片分成两个大的flex容器,给悬浮卡片设绝对定位脱离文档流:
<div layout="row" layout-fill style="position: relative;"> <!-- 左侧内容占满剩余宽度 --> <div flex> <!-- 顶部标题栏 --> <div class="container" layout="row" layout-xs="column"> <div flex="20" hide-sm></div> <div flex> <h1 style="margin-bottom: 20px">Which edition?</h1> </div> <div flex="20" hide-sm></div> </div> <!-- 三张卡片的布局不变 --> <div class="container" layout="row" layout-xs="column"> <div flex="20" hide-sm></div> <div flex> <!-- 卡片1 --> </div> <div flex> <!-- 卡片2 --> </div> <div flex> <!-- 卡片3 --> </div> </div> </div> <!-- 右侧悬浮卡片:sticky固定,宽度设为20% --> <div sticky style="position: sticky; top: 20px; width: 20%; z-index: 2; margin-right: 10%;"> <!-- 悬浮卡片内容不变 --> </div> </div>
重点提醒
- 把悬浮卡片上原来的
float:right和position:relative删掉,换成position:sticky(现代浏览器都支持这个属性) - 一定要给悬浮卡片的父容器设
position:relative,不然sticky会相对于整个页面定位,可能出问题 - 左侧内容的
margin-right要比悬浮卡片的宽度大一点,避免内容和卡片重叠 - 保留
z-index:2,确保悬浮卡片在左侧内容的上方,不会被遮挡
这样改完之后,左侧的三张卡片就能正常占满可用宽度,不会被压缩,而右侧的悬浮卡片滚动时依然能固定在你想要的位置~
内容的提问来源于stack exchange,提问作者konrad
相关产品推荐
相关产品推荐

