iOS 11.2.5下textarea旋转45deg时光标未同步旋转问题求助
解决iOS上旋转textarea光标异常的问题
相信你已经发现了,iOS Safari对应用了CSS旋转的textarea光标渲染有个挺烦人的bug——原生光标不会跟着元素一起旋转,反而显示成一个怪异的大框。这是因为Safari的文本光标渲染逻辑并没有适配CSS transform属性,下面给你几个可行的修复方案:
方案一:用伪元素模拟跟随旋转的光标
我们可以先隐藏原生光标,再用CSS伪元素做一个能跟着旋转的自定义光标,再配合JS实时调整位置:
.rotated-textarea { transform: rotate(45deg); caret-color: transparent; /* 隐藏原生光标 */ position: relative; --cursor-top: 50%; --cursor-left: 50%; } /* 模拟光标样式 */ .rotated-textarea::after { content: ''; position: absolute; width: 2px; height: 1.2em; background-color: #000; transform: rotate(-45deg); /* 反向旋转,抵消容器的旋转,保持光标垂直 */ animation: blink 1s step-end infinite; pointer-events: none; /* 不干扰输入操作 */ top: var(--cursor-top); left: var(--cursor-left); } @keyframes blink { 50% { opacity: 0; } }
然后补充一点JS代码,监听输入和点击事件,实时获取光标位置来调整伪元素的偏移:
const textarea = document.querySelector('.rotated-textarea'); // 监听需要更新光标位置的事件 textarea.addEventListener('input', updateCursor); textarea.addEventListener('click', updateCursor); textarea.addEventListener('focus', updateCursor); function updateCursor() { const selectionStart = textarea.selectionStart; if (!textarea.firstChild) return; const range = document.createRange(); const selection = window.getSelection(); range.setStart(textarea.firstChild, selectionStart); range.setEnd(textarea.firstChild, selectionStart); const rect = range.getBoundingClientRect(); const textareaRect = textarea.getBoundingClientRect(); // 计算并设置光标位置的CSS变量 textarea.style.setProperty('--cursor-top', `${rect.top - textareaRect.top}px`); textarea.style.setProperty('--cursor-left', `${rect.left - textareaRect.left}px`); }
方案二:反向旋转内部内容,规避textarea旋转
这个思路更简单:让外部容器旋转,而textarea本身反向旋转回来,这样textarea实际上没有被旋转,光标就能正常显示,只是视觉上整体是旋转的:
<div class="rotate-container"> <textarea class="no-rotate-textarea"></textarea> </div>
.rotate-container { transform: rotate(45deg); width: 300px; height: 200px; overflow: hidden; /* 裁剪textarea超出容器的部分 */ } .no-rotate-textarea { width: 100%; height: 100%; transform: rotate(-45deg); /* 反向旋转,抵消容器的旋转 */ padding: 20px; box-sizing: border-box; border: 1px solid #ccc; resize: none; }
这种方法不需要额外JS,原生光标完全正常,你只需要调整容器和textarea的尺寸、内边距,确保内容不会被裁剪,视觉对齐到位就行。
方案三:用contenteditable元素替代textarea
如果你的业务场景允许,可以把textarea换成contenteditable="true"的div,iOS对contenteditable元素的旋转兼容性要好很多,光标会自动跟随元素旋转:
<div class="rotated-editable" contenteditable="true"></div>
.rotated-editable { transform: rotate(45deg); width: 300px; height: 200px; border: 1px solid #ccc; padding: 10px; box-sizing: border-box; resize: vertical; /* 可选,模拟textarea的resize功能 */ }
需要注意的是,contenteditable和textarea的行为有差异,比如表单提交时需要手动获取它的内容,还要处理换行、格式保留等问题,需要根据你的实际需求调整。
内容的提问来源于stack exchange,提问作者BrunoLM
相关产品推荐
相关产品推荐

