文本方向(dir 属性)
世界上并非所有语言都是从左到右书写的。阿拉伯语、希伯来语等语言使用从右到左(RTL)的书写方向,而中文、英文等使用从左到右(LTR)的方向。dir 属性和 CSS Logical Properties 使得开发者能够轻松构建支持双向文本的网页。本节将详细介绍 dir 属性的用法、RTL 适配策略,以及现代 CSS Logical Properties 的应用。
前置知识
阅读本节前,建议先了解:字符编码(UTF-8)
文本方向概述
LTR 与 RTL
| 方向 | 英文缩写 | 代表语言 |
|---|---|---|
| 从左到右 | LTR | 中文、英文、日文、韩文、法文、德文等 |
| 从右到左 | RTL | 阿拉伯语、希伯来语、波斯语、乌尔都语等 |
| 双向 | BiDi | 混合 LTR 和 RTL 的内容 |
dir 属性
基本用法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>文本方向示例</title>
</head>
<body>
<!-- LTR(默认) -->
<p dir="ltr">这是从左到右的文本。</p>
<!-- RTL -->
<p dir="rtl">هذا نص من اليمين إلى اليسار.</p>
<!-- 自动检测 -->
<p dir="auto">Hello مرحبا 你好</p>
</body>
</html>dir 属性值
| 值 | 说明 | 适用场景 |
|---|---|---|
ltr | 从左到右 | 默认值,大多数语言 |
rtl | 从右到左 | 阿拉伯语、希伯来语等 |
auto | 浏览器自动检测 | 混合内容(如用户输入) |
文档级别方向
html
<!-- 中文网站(LTR) -->
<!DOCTYPE html>
<html lang="zh-CN" dir="ltr">
<body>...</body>
</html>
<!-- 阿拉伯语网站(RTL) -->
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<body>...</body>
</html>
<!-- 希伯来语网站(RTL) -->
<!DOCTYPE html>
<html lang="he" dir="rtl">
<body>...</body>
</html>元素级别方向
html
<!-- 在 LTR 文档中嵌入 RTL 内容 -->
<p>他说:<span lang="ar" dir="rtl">مرحبا بالعالم</span></p>
<!-- 用户评论(自动检测方向) -->
<div class="comment" dir="auto">
<!-- 如果用户输入的是阿拉伯语,自动显示为 RTL -->
<!-- 如果用户输入的是中文,自动显示为 LTR -->
</div>CSS Logical Properties
传统 CSS 属性使用物理方向(left/right/top/bottom),在 RTL 布局中需要反转。CSS Logical Properties 使用逻辑方向(inline/block),自动适应文本方向。
物理属性 vs 逻辑属性
| 传统物理属性 | CSS 逻辑属性 | LTR 中的效果 | RTL 中的效果 |
|---|---|---|---|
margin-left | margin-inline-start | 左外边距 | 右外边距 |
margin-right | margin-inline-end | 右外边距 | 左外边距 |
padding-left | padding-inline-start | 左内边距 | 右内边距 |
padding-right | padding-inline-end | 右内边距 | 左内边距 |
text-align: left | text-align: start | 左对齐 | 右对齐 |
text-align: right | text-align: end | 右对齐 | 左对齐 |
left | inset-inline-start | 左定位 | 右定位 |
right | inset-inline-end | 右定位 | 左定位 |
border-left | border-inline-start | 左边框 | 右边框 |
float: left | float: inline-start | 左浮动 | 右浮动 |
使用示例
html
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>CSS Logical Properties RTL 示例</title>
<style>
/* 传统方式:RTL 下需要覆盖 */
/* 不推荐 */
.box {
margin-left: 2rem;
padding-right: 1rem;
border-left: 3px solid #0066cc;
text-align: right;
float: left;
}
[dir="rtl"] .box {
margin-left: 0;
margin-right: 2rem;
padding-right: 0;
padding-left: 1rem;
border-left: none;
border-right: 3px solid #0066cc;
text-align: left;
float: right;
}
/* 逻辑属性方式:自动适应 */
/* 推荐 */
.logical-box {
margin-inline-start: 2rem; /* LTR=左,RTL=右 */
padding-inline-end: 1rem; /* LTR=右,RTL=左 */
border-inline-start: 3px solid #0066cc;
text-align: start; /* LTR=左,RTL=右 */
float: inline-start; /* LTR=左浮动,RTL=右浮动 */
}
</style>
</head>
<body>
<div class="logical-box">
<p>这段文字在 RTL 布局中自动适应方向。</p>
</div>
</body>
</html>逻辑尺寸属性
css
/* 物理 vs 逻辑 尺寸 */
.width → inline-size /* 宽度 */
.height → block-size /* 高度 */
.min-width → min-inline-size
.max-width → max-inline-size
.min-height → min-block-size
.max-height → max-block-size
/* 逻辑位置 */
.top → inset-block-start
.bottom → inset-block-end
/* 逻辑方向简写 */
.inset-inline: 1rem 2rem; /* 上下+左右 逻辑方向 */
.inset-block: 1rem 2rem;RTL 适配策略
镜像布局
RTL 网站通常是 LTR 网站的镜像:
LTR: [Logo] [Nav1] [Nav2] [Nav3] [Search]
RTL: [Search] [Nav3] [Nav2] [Nav1] [Logo]html
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>RTL 适配示例</title>
<style>
/* 使用逻辑属性自动镜像 */
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding-inline: 2rem; /* LTR=左右,RTL=右左 */
}
.logo {
margin-inline-end: auto; /* LTR=右,RTL=左 */
}
.nav {
display: flex;
gap: 1.5rem;
list-style: none;
}
.content {
display: grid;
grid-template-columns: 1fr 3fr;
gap: 2rem;
}
/* 使用 start/end 而非 left/right */
.sidebar {
border-inline-start: 2px solid #e0e0e0;
padding-inline-start: 1.5rem;
}
/* 文本对齐自动适应 */
.text-start { text-align: start; }
.text-end { text-align: end; }
</style>
</head>
<body>
<header class="header">
<div class="logo">شركة</div>
<nav>
<ul class="nav">
<li><a href="/">الرئيسية</a></li>
<li><a href="/products">المنتجات</a></li>
<li><a href="/about">من نحن</a></li>
</ul>
</nav>
</header>
<div class="content">
<aside class="sidebar">
<!-- 侧边栏自动移到右侧(RTL 中) -->
<h2>القائمة الجانبية</h2>
<ul>
<li><a href="#">رابط 1</a></li>
<li><a href="#">رابط 2</a></li>
</ul>
</aside>
<main>
<h1>مرحبا بك</h1>
<p>هذا هو محتوى الصفحة الرئيسية.</p>
</main>
</div>
</body>
</html>不需要镜像的元素
| 元素 | 是否镜像 | 原因 |
|---|---|---|
| 文字内容 | 否 | 方向由 dir 属性控制 |
| 电话号码 | 否 | 数字方向固定 |
| URL | 否 | 网址方向固定 |
| 图标 | 否 | 方向固定的图标不镜像 |
| 时间显示 | 否 | 时间格式不变 |
| 箭头图标 | 可能 | 指向性箭头需要镜像 |
图标镜像
css
/* 需要镜像的图标 */
.arrow-icon {
transform: scaleX(1); /* LTR */
}
[dir="rtl"] .arrow-icon {
transform: scaleX(-1); /* RTL:水平翻转 */
}
/* 使用 CSS 逻辑属性实现 */
.arrow-icon {
transform: scaleX(var(--direction, 1));
}
[dir="rtl"] {
--direction: -1;
}bdi 元素
<bdi>(Bidirectional Isolate)元素用于隔离双向文本,防止其影响周围的文本方向:
html
<!-- 用户名可能是任意语言 -->
<p>用户 <bdi>إبراهيم</bdi> 发布了 5 条评论。</p>
<!-- bdi 确保阿拉伯语用户名不影响周围中文文本的方向 -->
<!-- 不使用 bdi 的问题 -->
<p>用户 إبراهيم 发布了 5 条评论。</p>
<!-- 阿拉伯语用户名可能使 "5 条评论" 的方向被反转 -->
<!-- bdo 元素:强制覆盖文本方向 -->
<bdo dir="rtl">这段文字会被强制从右到左显示</bdo>实战示例:双向支持页面
html
<!DOCTYPE html>
<html lang="zh-CN" dir="ltr">
<head>
<meta charset="UTF-8">
<title>双向文本支持页面</title>
<style>
/* 使用逻辑属性 */
:root {
--primary: #0066cc;
--bg: #ffffff;
--text: #1a1a2e;
--border: #e0e0e0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
color: var(--text);
background: var(--bg);
padding-inline: 2rem;
max-inline-size: 800px;
margin-inline: auto;
}
.card {
border: 1px solid var(--border);
border-radius: 8px;
padding: 1.5rem;
margin-block: 1rem;
}
.comment {
display: flex;
gap: 1rem;
margin-block: 1rem;
}
.avatar {
width: 48px;
height: 48px;
border-radius: 50%;
background: var(--primary);
color: white;
display: flex;
align-items: center;
justify-content: center;
}
.comment-content {
flex: 1;
}
.comment-meta {
font-size: 0.875rem;
color: #666;
margin-block-end: 0.5rem;
}
/* dir="auto" 自动检测方向 */
.user-text {
dir: auto;
}
</style>
</head>
<body>
<h1>多语言评论</h1>
<!-- 中文评论 -->
<div class="comment">
<div class="avatar">张</div>
<div class="comment-content">
<div class="comment-meta">张三 · 2024-01-15</div>
<p class="user-text">这个教程写得太好了,收藏了!</p>
</div>
</div>
<!-- 阿拉伯语评论 -->
<div class="comment">
<div class="avatar">إ</div>
<div class="comment-content">
<div class="comment-meta"><bdi>إبراهيم</bdi> · 2024-01-14</div>
<p class="user-text">هذا الدرس ممتاز! شكرا لك.</p>
</div>
</div>
<!-- 希伯来语评论 -->
<div class="comment">
<div class="avatar">י</div>
<div class="comment-content">
<div class="comment-meta"><bdi>יעל</bdi> · 2024-01-13</div>
<p class="user-text">מדריך מעולה! תודה רבה.</p>
</div>
</div>
<!-- 混合内容 -->
<div class="card">
<h2>混合方向文本</h2>
<p>
在中文中引用英文:<span lang="en" dir="ltr">Hello World</span>,以及阿拉伯语:
<span lang="ar" dir="rtl">مرحبا</span>。
</p>
</div>
</body>
</html>注意事项
dir属性影响整个子树:在元素上设置dir会影响所有子元素- 混合语言使用
bdi:防止双向文本影响周围内容 - CSS 逻辑属性不改变方向:只是让属性值自适应
dir方向 - 测试 RTL 布局:确保镜像后布局正确
- 图标注意方向:方向性图标(箭头等)需要在 RTL 中翻转
最佳实践
- 使用 CSS Logical Properties 替代物理方向属性
- 在
<html>标签上正确设置dir属性 - 混合语言内容使用
dir="auto"或<bdi>元素 - 测试 LTR 和 RTL 两种布局
- 镜像布局时注意图标方向
- 使用
[dir="rtl"]选择器处理特殊 RTL 样式
下一节
继续学习:多语言页面设计