css:touch-action导致安卓无法滚动页面

本文探讨了CSS touch-action属性的使用场景与问题,解析了其在不同设备上的表现差异,尤其是在安卓设备上的滚动问题,并提供了合理的解决方案。同时,文章还分享了作者在实践过程中的经验教训。
部署运行你感兴趣的模型镜像

前言

相信大家搜css touch-action很容易搜到一批文章,但感觉自己还是需要写下自己这这个过程中的一些探索经历。

之所以写,是因为单独去学知识点或者单独看一篇文章其实很简单的,难的是在自己实践中,因为一个问题找一个方案,然后又引起另外一个问题,而这个不断发现问题的过程非常低效,需要各种尝试和理解。

使用css touch-action的原因

在其官方的说明中:是否,以及以何种方式,给定的区域,可以由用户通过触摸屏操作(例如,通过平移或缩放内置的浏览器功能)

但我最初并不是因为这个来使用它的,后续会补充一篇使用这个特性做出来的效果。我用这个属性是因为自己在使用antd-mobile的走马灯时候,在控制台代码警告,内容是这样的:

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See…

看到这样的报错,作为程序员,职业病肯定是要查看原因的,虽然不影响正常使用。经过查阅,其简单的描述就是这样的:Passive event listeners,做了移动端的优化。看完一脸懵逼。其实就是是否阻止默认事件200ms延迟然后再执行滚动行为,而之前的fastclick就是通过去掉这部分来避免点击延迟的。

For instance, in Chrome for Android 80% of the touch events that block
scrolling never actually prevent it. 10% of these events add more than
100ms of delay to the start of scrolling, and a catastrophic delay of
at least 500ms occurs in 1% of scrolls.

想知道更多,可以参考这篇,写的比较详细了: 移动Web滚动性能优化: Passive event listeners

然后知道原因不够,解决方案是什么?

能搜到的方案是两种,一种是通过css方式,一种是通过js的方式。 css方式:比较简单

touch-action:none 

js方式:在touch的事件监听方法上绑定第三个参数{ passive: false }

elem.addEventListener(
  'touchstart',
  fn,
  { passive: false }
);

使用touch-action之后,问题来了

然后当然是开心的用第一种方案把这行css写到全局中,结果就带来了灾难。 什么问题呢?就是ios基本都可以的,但是安卓中的页面滚动都没了。这是为什么呢?这个就要看下touch-action的更官方的触摸说明了。

默认情况下,平移(滚动)和捏手势由浏览器独占处理。当浏览器开始处理触摸手势时,使用的应用程序Pointer_events将收到一个pointercancel事件。 通过明确指定浏览器应该处理哪些手势,应用程序可以为其余手势提供自己的行为,pointermove并pointerup为其余的手势提供监听器。应用程序使用Touch_events。 通过调用禁用浏览器处理手势preventDefault(),但也应该使用触摸动作来确保浏览器在调用任何事件侦听器之前知道应用程序的意图。当手势开始时,浏览器将触摸元素及其所有祖先的触摸动作值与实现手势的触摸动作值(换句话说,第一个包含滚动元素)相交。 这意味着在实践中,触摸动作通常只应用于具有一些自定义行为的单个元素,而不需要在该元素的任何后代上明确指定触摸动作。手势开始后,触摸动作值的更改将不会对当前手势的行为产生任何影响。

文档参考来源:touch-action

说人话

这段话阐明的就是触摸事件整个的进行过程,既然它可以通过css来约定滚动的行为,那么就意味着你写了touch-action:none,就会导致原来的页面滚动失效了。这就是安卓上无法页面滚动的原因。

为什么ios没有受影响呢,我觉得可能是ios默认支持touch事件的原因吧。如果你知道底层的原因或者详细的文档说明,可以告诉我哦。

怎么解决呢

先临时把对应的touch:none,全局的写法去掉了,用了js的部分去完成或者只在控制需要的元素内进行指定这行代码。由此也总结了几个问题或者教训吧。

  • 在写全局样式的要注意影响范围
  • 在每次提交代码的时候尽可能针对不确定的部分增加备注,风险埋点,因为这次刚好是因为用户有反馈这个问题,我想到了是加了这行代码的原因,但如果是其他时候或者过了很久,其实很难定位到是因为这行代码的原因。我遇到这个问题的时候,第一感觉还是是否是脚本错误了,是否是兼容问题。如果是这样排查的话,就会浪费比较多的时间。甚至中间还找群友讨论,他们建议是否更换为绝对定位的方案,那样就真走偏了。
  • 问题拿到后的冷静分析,拿到这个问题不要过于着急,还是要分析下产生问题的原因,尤其是机型,因为我们之前做测试都是模拟器和苹果的ios,而这次报问题的都是安卓的机型,而且是小米56,坚果,华为等。联想到这些安卓机型,那么定位到可能是 :代码兼容部分的版本过低,这些不支持;代码某部分是对ios和安卓有区分解释的,和系统有关,版本无关。

更多延伸与拓展

通过touch-action可以做什么效果呢?

  • 禁止默认的滚动touch-action:none
  • 可以控制用户行为的处理细节,比如只接受x或者y方向的变化,来影响行为,确定行为边界
  • 优化用户多次点击造成界面所放
  • 更多等待你的发掘

更多

说明:如果你想更好的使用滚动相关的体验,还是入手框架吧,不然坑太多,iscroll,better-scroll(一般滚动组件依赖的库).me-scroll(个人推荐)都是不错的选择

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

<template> <view class="container"> <view class="banner-section"> <image class="banner-image" src="/static/IntegrityCulture.png" /> </view> <view class="title">廉洁文化资讯</view> <view class="news-list"> <scroll-view scroll-y="true" :enhanced="true" :use-passive="true" :show-scrollbar="false" class="scroll-container" > <view v-for="item in newsList" :key="item.id" class="news-item" @click="navigateToDetail(item)" > <view class="news-content"> <text class="news-title">{{ item.title }}</text> <text class="news-summary">{{ item.summary }}</text> <text class="news-date">{{ item.publishDate }}</text> </view> <view class="status-box" :class="item.read ? 'read' : 'unread'" > {{ item.read ? '已阅' : '未阅' }} </view> </view> </scroll-view> </view> </view> </template> <script setup> import { ref, onMounted } from 'vue'; const newsList = ref([]); const fetchData = () => { setTimeout(() => { newsList.value = [ { id: 1, title: '廉洁从业,从我做起', summary: '廉洁从业是每一位员工应尽的责任和义务,本文介绍了公司廉洁文化建设的相关要求和实践。', publishDate: '2024-09-10', read: true }, { id: 2, title: '加强反腐倡廉,构建阳光企业', summary: '公司持续加强反腐倡廉工作,推动形成风清气正的企业文化氛围。', publishDate: '2024-09-08', read: false }, { id: 3, title: '廉洁文化进班组,清风正气润人心', summary: '公司组织廉洁文化进班组活动,通过宣传、培训等方式提升员工廉洁意识。', publishDate: '2024-09-05', read: false } ]; }, 500); }; onMounted(() => { fetchData(); // 添加被动事件监听器(可选) setTimeout(() => { const scrollEl = uni.createSelectorQuery().select('.scroll-container'); scrollEl.boundingClientRect(data => { if (data) { console.log('滚动容器高度:', data.height); } }).exec(); }, 300); }); const navigateToDetail = (item) => { uni.navigateTo({ url: `/pages/IntegrityCulture/IntegrityCultureDetail/IntegrityCultureDetail?id=${item.id}` }); }; </script> <style scoped> /* 被动事件优化 */ scroll-view { touch-action: pan-y; -webkit-overflow-scrolling: touch; overflow-scrolling: touch; } .container { padding: 30rpx; background-color: #f9f9f9; height: 100vh; overflow: hidden; box-sizing: border-box; } .banner-section { margin-bottom: 40rpx; border-radius: 16rpx; overflow: hidden; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1); } .banner-image { width: 100%; height: 320rpx; display: block; } .title { font-size: 36rpx; font-weight: bold; text-align: center; margin-bottom: 40rpx; } .news-list { background-color: #fff; border-radius: 16rpx; overflow: hidden; height: calc(100vh - 500rpx); min-height: 300rpx; } .scroll-container { height: 100%; } .news-item { padding: 30rpx; position: relative; display: flex; justify-content: space-between; align-items: flex-start; border-bottom: 1rpx solid #eee; } .news-content { flex: 1; padding-right: 20rpx; } .news-title { font-size: 32rpx; font-weight: bold; color: #333; display: block; margin-bottom: 10rpx; } .news-summary { font-size: 28rpx; color: #666; display: block; margin-bottom: 10rpx; line-height: 1.5; } .news-date { font-size: 24rpx; color: #999; display: block; } .status-box { padding: 8rpx 16rpx; font-size: 24rpx; border-radius: 8rpx; min-width: 80rpx; text-align: center; } .status-box.read { background-color: rgba(76, 175, 80, 0.1); color: #4caf50; } .status-box.unread { background-color: rgba(244, 67, 54, 0.1); color: #f44336; } /* 移动设备优化 */ @media (max-height: 600px) { .news-list { height: calc(100vh - 450rpx); } } </style> 我想要news-list板块内部滚动不影响页面其他内容,同时去掉滚动
08-15
.mobile-carousel { width: 100vw; height: 100vh; overflow: hidden; position: fixed; top: 0; left: 0; margin: 0; padding: 0; z-index: 1000; touch-action: pan-y; background: #000; } .slides { display: flex; height: 100%; transition: transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1); /* 更顺滑的缓动函数 */ } .slide { flex: 0 0 100vw; /* 宽度精确匹配视口 */ position: relative; height: 100vh; padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); box-sizing: border-box; /* 包含内边距 */ } .slide img { width: 100%; height: 100%; object-fit: cover; display: block; /* 防止长按菜单 */ pointer-events: none; -webkit-touch-callout: none; } .slide-hint { position: absolute; bottom: calc(10vh + env(safe-area-inset-bottom)); /* 避开底部安全区域 */ right: max(5vw, env(safe-area-inset-right)); /* 适配刘海屏 */ background: rgba(0,0,0,0.75); color: #fff; padding: 12px 20px; border-radius: 30px; font-size: 16px; animation: hintPulse 1.5s infinite; backdrop-filter: blur(4px); /* 毛玻璃效果 */ z-index: 10; font-weight: 500; } @keyframes hintPulse { 0% { opacity: 0.7; transform: translateX(0) scale(0.98); } 50% { opacity: 1; transform: translateX(-8px) scale(1.03); } 100% { opacity: 0.7; transform: translateX(0) scale(0.98); } } /* 全面屏适配 */ @media screen and (max-aspect-ratio: 9/16) { .slide img { object-fit: contain; /* 超长屏使用contain模式 */ } } /* 禁用iOS橡皮筋效果 */ body { overscroll-behavior: none; } 为什么屏幕顶部和底部会有一块黑色背景区域 我希望有这个区域 我希望图片占据整个屏幕
09-21
<template> <!--首次加载数据效果--> <up-loading-page loadingText="" :loading="onloading" bgColor="#fff" iconSize="80px" zIndex="999" image="https://m.nocexpo.com/statics/js/modules/h5/jinn/loading.gif"> </up-loading-page> <!-- <root> --> <root v-if="!onloading"> <gb :message="gbConfig.message"></gb> <view class="container" :style="`height: ${screenArInfo.middleHeight}px;overflow:hidden;`"> <view scroll-y class="scroll-view"> <view class="head" :style="`width:${headSize.right}px`"> <view class="first"> <view class="lan"></view> <view class="first-c"> <view>仅看差异</view> <view class="switch-container"> <switch :checked="showOnlyDiff" @change="toggleDiffMode" color="rgba(16, 98, 202, 1)" style="transform:scale(0.7)"></switch> </view> </view> <view class="lan"></view> </view> <view class="data"> <view class="data-c"> <view class="item" v-for="(product, index) in products" :key="index" :class="dingFlag && index === 0?'item_first':''"> <!--固定右侧的小白条--> <view class="ding-right"></view> <view :class="`item-c item-${index}`"> <view class="icon"> <view class="din" @click.stop="toggleDing(index)"> <pic v-if="dingFlag && index === 0" src="icon_ding_active.png" prefix="image" cstyle="width:25.44rpx;height:25.42rpx" /> <pic v-else src="icon_ding.png" prefix="image" cstyle="width:25rpx;height:25rpx" /> {{ dingFlag && index === 0 ? '钉住' : '钉在左侧' }} </view> <!-- 使用view包装pic组件以确保事件能正确触发 --> <view @click.stop="removeProduct(index)" class="close"> <pic src="icon_close.png" prefix="image" cstyle="width:16.45rpx;height:16.01rpx" /> </view> </view> <view class="title"> {{ product.seriesName }} </view> <view class="grey"> <!-- {{ product.brand }} --> {{ product.name }} </view> </view> </view> <!-- <view class="last" @click="addProduct"> <view>添加机型</view> <view class="i-img"> <pic src="icon_add.png" prefix="image" cstyle="width:34rpx;height:34rpx" /> </view> </view>--> </view> </view> </view> <!-- <view class="hr"></view> --> <view class="data-list"> <view class="datas"> <view class="group-name" :style="`width:${headSize.right-5}px`"> <view>参数</view> </view> <view class="group-data" :style="`width:${headSize.right-5}px`"> <view class="data"> <view class="item"> <view class="d">品牌</view> <view class="d" v-for="(product, index) in products" :key="index" :class="dingFlag && index==0?'item_first':''"> {{ product.brand }} </view> </view> <view class="item"> <view class="d">价格</view> <view class="d" v-for="(product, index) in products" :class="dingFlag && index==0?'item_first':''"> {{ convertPrice(product) }} </view> </view> </view> </view> </view> <view class="datas" v-for="(group, groupIndex) in filteredAttributeGroups" :key="groupIndex"> <view class="group-name" :style="`width:${headSize.right-5}px`"> <view>{{ group.groupName }}</view> </view> <view class="group-data" :style="`width:${headSize.right-5}px`"> <view class="data"> <view class="item" v-for="(attr, attrIndex) in group.attributes" :key="attrIndex"> <view class="d">{{ attr.attrName }}</view> <view class="d" v-for="(product, productIndex) in products" :key="productIndex" :class="`${attr.isDiff?'diff':''} ${dingFlag && productIndex==0?'item_first':''}`"> {{ getProductAttributeValue(product, group.groupName, attr.attrName) }} </view> </view> </view> </view> </view> </view> <view v-if="!screenArInfo.boolStripe" style="height: 20rpx;"></view> </view> </view> </root> </template> <script setup> import { ref, reactive, computed, onMounted } from "vue" import { useStore } from 'vuex'; import infoApi from '@/api/product/equipment/info.js'; import utilApi from "@/utils/util.js"; import classifyApi from '@/api/productseries.js'; const gbConfig = ref({ psize: {}, message: { type: 1, TitleText: "设备参数", url: "pages/Choose/parameter/index" } }) const onloading = ref(true); const dingFlag = ref(false); const showOnlyDiff = ref(false); // 控制是否仅显示差异 const products = ref([]); const attributeGroups = ref([]); const screenArInfo = computed(() => { return useStore().getters.getScreenInfo }) const headSize = ref({}); const productIds = ref(''); // 计算属性,根据showOnlyDiff过滤属性组 const filteredAttributeGroups = computed(() => { if (!showOnlyDiff.value) { // 如果不显示差异,则返回所有属性组 return attributeGroups.value; } else { // 如果仅显示差异,则过滤掉isDiff为false的属性组和属性 return attributeGroups.value .filter(group => group.isDiff) // 过滤属性组 .map(group => { // 过滤属性 const filteredAttributes = group.attributes.filter(attr => attr.isDiff); return { ...group, attributes: filteredAttributes }; }) .filter(group => group.attributes.length > 0); // 过滤掉没有属性的组 } }); // 根据系列id获取所有型号id const dataAll = ref([]); const IDS = ref(''); const getSeriesId = async (id) => { const params = { seriesId: id, } try { const res = await classifyApi.getAllId(params); if (res.data.code === 0) { console.log(res.data.list, 'res---'); // 检查数据结构,确保products正确赋值 if (Array.isArray(res.data.list)) { // 假设res.data.list中的每个item需要映射到products的格式 // 创建一个临时数组存储转换后的数据 const formattedProducts = []; // 遍历响应数据 res.data.list.forEach(item => { // 检查item是否包含products数组 if (item.products && Array.isArray(item.products)) { // 将每个product添加到formattedProducts中,并确保包含模板中使用的属性 item.products.forEach(product => { // 确保产品对象包含必要的属性,如seriesName, name, brand等 formattedProducts.push({ id: product.id, seriesName: product.seriesName || item.seriesName || '未知系列', name: product.name || '未知型号', brand: product.brand || '未知品牌', quoted: product.quoted || 2, // 默认暂无报价 price: product.price || 0, attributes: product.attributes || {} }); }); } else { // 如果item本身就是产品对象,则直接添加 formattedProducts.push({ id: item.id, seriesName: item.seriesName || '未知系列', name: item.name || '未知型号', brand: item.brand || '未知品牌', quoted: item.quoted || 2, price: item.price || 0, attributes: item.attributes || {} }); } }); // 赋值给products products.value = formattedProducts; // 重新生成attributeGroups if (formattedProducts.length > 0) { regenerateAttributeGroups(); } console.log('处理后的产品数据:', products.value); } // 计算高度 setTimeout(() => { getHeight() }, 100); } onloading.value = false; // 加载完成后关闭加载状态 } catch (error) { console.error('获取系列型号ID失败:', error); onloading.value = false; // 出错时也关闭加载状态 } } /** * 切换差异显示模式 */ function toggleDiffMode(event) { showOnlyDiff.value = event.detail.value; } /** * 添加产品 */ function addProduct() { uni.navigateTo({ url: '/pages/product/equipment/list/list' }) } /** * 删除指定索引的产品 */ function removeProduct(index) { // 检查产品数量是否大于1,否则不允许删除 if (products.value.length <= 1) { console.log('至少保留一个设备'); // 这里可以添加用户提示,比如使用uni.showToast uni.showToast({ title: '至少保留一个设备', icon: 'none', duration: 2000 }); return; } // 检查索引是否有效 if (index < 0 || index >= products.value.length) { console.error('删除型号无效:', index); return; } // 从products数组中删除指定索引的产品 products.value.splice(index, 1); console.log('products after removal:', products.value); // 重新生成attributeGroups数据 regenerateAttributeGroups(); // 确保onloading状态正确(在某些情况下可能需要) onloading.value = false; } /** * 钉住/取消钉住功能 * @param {Number} index - 要钉住的产品索引 */ async function toggleDing(index) { // 如果点击的是第一个产品(索引为0) if (index === 0) { // 切换钉住状态 dingFlag.value = !dingFlag.value; // 如果钉住状态为true,确保该产品保持在第一位 if (dingFlag.value && products.value.length > 1) { // 第一个产品已经是索引0,无需移动 console.log('产品已钉住'); } } else { // 如果点击的不是第一个产品,则需要将该产品移动到第一位并钉住 if (index >= 0 && index < products.value.length) { // 获取要移动的产品 const productToMove = products.value[index]; // 从原位置删除并添加到第一位 products.value.splice(index, 1); products.value.unshift(productToMove); // 设置钉住状态 dingFlag.value = true; // 重新生成属性组 regenerateAttributeGroups(); console.log('产品已移动到第一位并钉住'); } } } /** * 根据当前products重新生成attributeGroups */ function regenerateAttributeGroups() { // 创建一个映射来存储所有属性组和属性 const attributeMap = new Map(); // 遍历所有产品,收集所有的属性组和属性 products.value.forEach(product => { if (product.attributes) { Object.keys(product.attributes).forEach(groupName => { // 如果属性组不存在,则创建它 if (!attributeMap.has(groupName)) { attributeMap.set(groupName, new Set()); } // 将该组下的所有属性添加到集合中 const groupAttrs = product.attributes[groupName]; Object.keys(groupAttrs).forEach(attrName => { attributeMap.get(groupName).add(attrName); }); }); } }); // 将Map转换为与原来格式相同的数组 const newAttributeGroups = []; attributeMap.forEach((attrsSet, groupName) => { const attributes = []; attrsSet.forEach(attrName => { // 检查该属性是否在所有产品中都有不同的值 let isDiff = checkAttributeIsDiff(groupName, attrName); attributes.push({ attrName: attrName, isDiff: isDiff }); }); // 检查该属性组是否在不同产品中有不同的属性 let groupIsDiff = attributes.some(attr => attr.isDiff); newAttributeGroups.push({ groupName: groupName, attributes: attributes, isDiff: groupIsDiff }); }); // 更新attributeGroups attributeGroups.value = newAttributeGroups; // 重新计算高度 // setTimeout(() => { // getHeight(); // }, 1000); } /** * 检查指定属性在所有产品中是否具有不同值 */ function checkAttributeIsDiff(groupName, attrName) { let values = []; // 收集所有产品的该属性值 products.value.forEach(product => { if (product.attributes && product.attributes[groupName] && product.attributes[groupName][attrName]) { values.push(product.attributes[groupName][attrName]); } else { values.push(undefined); } }); // 检查是否所有定义的值都相同 const firstValue = values[0]; return !values.every(value => value === firstValue); } /** * 获取对比数据 */ // async function fetchContrastData() { // if (!productIds.value) return; // try { // const response = await infoApi.getproductcontrast(productIds.value) // if (response.data.code === 0) { // products.value = response.data.list[0].products || [] // attributeGroups.value = response.data.list[0].attributeGroups || [] // onloading.value = false; // 关闭加载动画 // // 计算高度 // setTimeout(() => { // getHeight() // }, 100); // } // } catch (error) { // console.error('获取对比数据失败:', error) // onloading.value = false; // 出错时也关闭加载动画 // } // } function convertPrice(item) { if (item.quoted === 1) { return "¥" + utilApi.handlePrice(item.price) + "起" } else if (item.quoted === 0) { return "询价" } else { return "暂无报价" } } /** * 此方法数据加载后执行,获取元素成开的高度 */ function getHeight() { const query = uni.createSelectorQuery(); // query.selectAll('.head').boundingClientRect(data => { // headSize.value = data[0] // }).exec(); // console.log(headSize.value.right, 2222222222, ".item-" + (products.value.length - 1)); if (!headSize.value.right) { query.selectAll('.item-' + (products.value.length - 1)).boundingClientRect(data => { headSize.value = data[0]; }).exec(); } } function getProductAttributeValue(product, groupName, attrName) { if (product.attributes && product.attributes[groupName] && product.attributes[groupName][attrName] && product.attributes[groupName][attrName].length > 0) { return product.attributes[groupName][attrName]; } else { return '-'; } } // 存储页面参数 const pageOptions = ref({}); onMounted(() => { // 获取URL参数 const pages = getCurrentPages() const currentPage = pages[pages.length - 1] pageOptions.value = currentPage.options || {} productIds.value = pageOptions.value.productIds || '' // 确保有seriesId参数再调用 if (pageOptions.value.seriesId) { getSeriesId(pageOptions.value.seriesId); } else { console.warn('缺少seriesId参数'); onloading.value = false; } }); </script> <style lang="scss" scoped> .container { background-color: #fff; } .scroll-view { height: 100%; overflow-y: auto; .data-list { padding-top: 10rpx; padding-bottom: 2rpx; .datas { .group-name { font-size: 28rpx; line-height: 54rpx; font-weight: 600; display: flex; view:first-child { position: sticky; left: 26rpx; } } .group-data { display: flex; align-items: center; padding-right: 16rpx; position: relative; box-shadow: 0px 4rpx 6rpx rgba(0, 0, 0, 0.1); .data { border-top: 2rpx solid rgba(209, 224, 255, 1); .item { display: flex; padding-left: 26rpx; .d { display: flex; justify-content: center; align-items: center; flex: 0 0 auto; text-align: center; width: 200rpx; flex-shrink: 0; padding: 10rpx 16rpx; font-size: 24rpx; min-height: 60rpx; color: rgba(56, 56, 56, 1); border-right: 2rpx solid rgba(209, 224, 255, 1); border-bottom: 2rpx solid rgba(209, 224, 255, 1); word-wrap: break-word; word-break: break-word; white-space: pre-wrap; .ding-right { display: none; } } .d:last-child { margin-right: 0px; } .d:first-child { position: sticky; left: 26rpx; flex-shrink: 0; width: 175rpx; flex: 0 0 auto; font-size: 28rpx; z-index: 4; color: rgba(0, 0, 0, 1); background: rgba(239, 244, 255, 1); border-left: 2rpx solid rgba(209, 224, 255, 1); &:before { position: absolute; content: ""; z-index: 3; top: -4%; left: -28rpx; height: 106%; width: 26rpx; background-color: #fff; } } .d.diff { background: rgba(255, 245, 242, 1); color: rgba(16, 98, 202, 1); } } .item_first { position: sticky; left: 233rpx; background-color: #fff; } } } } } } .hr { box-shadow: 0px 4rpx 6rpx rgba(0, 0, 0, 0.1); position: fixed; left: 0px; top: 363rpx; width: 100%; z-index: 10; height: 2rpx; background: #fff; } .head { display: flex; padding: 0rpx 0px 18rpx 0rpx; position: sticky; top: 0px; z-index: 9; height: 160rpx; background-color: #fff; box-shadow: 0px 4rpx 6rpx rgba(0, 0, 0, 0.1); .first { position: sticky; left: 0rpx; display: flex; .lan { width: 36rpx; height: 165rpx; position: relative; z-index: 8; background-color: #fff; margin-right: -10rpx; } .lan:last-child { width: 24rpx; margin-left: -10rpx; margin-right: 0px; } .first-c { width: 200rpx; height: 160rpx; flex: 0 0 auto; z-index: 9; border-radius: 12rpx; background: rgba(255, 245, 242, 1); color: rgba(0, 0, 0, 1); font-size: 24rpx; text-align: center; border: 2rpx solid rgba(255, 230, 224, 1); view:first-child { font-size: 24rpx; padding: 36rpx 0px 0px; } view:last-child { display: flex; align-items: center; justify-content: center; height: 46rpx; margin-top: 16rpx; } } } .data { flex: 0 0 auto; .data-c { width: 100%; display: flex; align-items: center; .item { flex-shrink: 0; margin: 0px 7rpx; .ding-right { display: none; } .item-c { width: 208rpx; height: 160rpx; padding: 0px 0rpx 0rpx 10rpx; display: inline-block; border-radius: 12rpx; background: rgba(239, 244, 255, 1); border: 2rpx solid rgba(209, 224, 255, 1); .icon { display: flex; justify-content: space-between; .din { display: flex; align-items: center; font-size: 20rpx; gap: 10rpx; color: rgba(97, 97, 97, 1); } .close { padding: 15rpx; } } .title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: rgba(46, 45, 45, 1); font-size: 24rpx; font-weight: 600; padding-right: 10rpx; } .grey { word-wrap: break-word; height: 70rpx; word-break: normal; font-size: 24rpx; margin-top: 5rpx; line-height: 35rpx; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; /* 限制最多显示3行 */ overflow: hidden; text-overflow: ellipsis; /* 可选,部分浏览器不生效 */ word-break: break-word; color: rgba(56, 56, 56, 1); padding-right: 10rpx; } } } .item:first-child { margin-left: 0px; } .item_first { position: sticky; left: 242rpx; margin-left: 0px; .item-c { position: relative; z-index: 4; } .ding-right { position: absolute; width: 16rpx; height: 100%; right: -10rpx; top: 0px; z-index: 3; display: block; background: #fff; } } } } } .param-title { color: rgba(0, 0, 0, 1); font-size: 28rpx; font-weight: 555; padding: 20rpx 26rpx; } </style>在安卓正常显示 在ios会出现横向滚动时纵向也会滚动的情况 分析代码 找出什么原因
最新发布
10-31
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值