Skip to main content Skip to docs navigation

RTL

了解如何在 Bootstrap 的布局、组件和工具中启用对从右到左文本的支持。

熟悉

¥Get familiar

我们建议你先阅读我们的 入门介绍页面 来熟悉 Bootstrap。运行完成后,请继续阅读此处了解如何启用 RTL。

¥We recommend getting familiar with Bootstrap first by reading through our Getting Started Introduction page. Once you’ve run through it, continue reading here for how to enable RTL.

你可能还想阅读 RTLCSS 项目,因为它为我们的 RTL 方法提供了动力。

¥You may also want to read up on the RTLCSS project, as it powers our approach to RTL.

Bootstrap 的 RTL 功能仍处于实验阶段,将根据用户反馈进行改进。发现了什么问题或有改进建议?提交问题,我们期待你的见解。

¥Bootstrap’s RTL feature is still experimental and will evolve based on user feedback. Spotted something or have an improvement to suggest? Open an issue, we’d love to get your insights.

必需的 HTML

¥Required HTML

在 Bootstrap 支持的页面中启用 RTL 有两个严格的要求。

¥There are two strict requirements for enabling RTL in Bootstrap-powered pages.

  1. <html> 元素上设置 dir="rtl"

    ¥Set dir="rtl" on the <html> element.

  2. <html> 元素上添加适当的 lang 属性,例如 lang="ar"

    ¥Add an appropriate lang attribute, like lang="ar", on the <html> element.

从这里,你需要包含我们 CSS 的 RTL 版本。例如,以下是启用了 RTL 的编译和压缩 CSS 样式表:

¥From there, you’ll need to include an RTL version of our CSS. For example, here’s the stylesheet for our compiled and minified CSS with RTL enabled:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.rtl.min.css" integrity="sha384-q8+l9TmX3RaSz3HKGBmqP2u5MkgeN7HrfOJBLcTgZsQsbrx8WqqxdA5PuwUV9WIx" crossorigin="anonymous">

入门模板

¥Starter template

你可以看到上述要求反映在这个修改后的 RTL 入门模板中。

¥You can see the above requirements reflected in this modified RTL starter template.

<!doctype html>
<html lang="ar" dir="rtl">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.rtl.min.css" integrity="sha384-q8+l9TmX3RaSz3HKGBmqP2u5MkgeN7HrfOJBLcTgZsQsbrx8WqqxdA5PuwUV9WIx" crossorigin="anonymous">

    <title>مرحبًا بالعالم!</title>
  </head>
  <body>
    <h1>مرحبًا بالعالم!</h1>

    <!-- Optional JavaScript; choose one of the two! -->

    <!-- Option 1: Bootstrap Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/js/bootstrap.bundle.min.js" integrity="sha384-k6d4wzSIapyDyv1kpU366/PK5hCdSbCRGRCMv+eplOQJWyd1fbcAu9OCUj5zNLiq" crossorigin="anonymous"></script>

    <!-- Option 2: Separate Popper and Bootstrap JS -->
    <!--
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/js/bootstrap.min.js" integrity="sha384-VQqxDN0EQCkWoxt/0vsQvZswzTHUVOImccYmSyhJTp7kGtPed0Qcx8rK9h9YEgx+" crossorigin="anonymous"></script>
    -->
  </body>
</html>

RTL 示例

¥RTL examples

从我们的多个 RTL 示例 之一开始。

¥Get started with one of our several RTL examples.

方法

¥Approach

我们在 Bootstrap 中构建 RTL 支持的方法有两个重要的决定,它们会影响我们编写和使用 CSS 的方式:

¥Our approach to building RTL support into Bootstrap comes with two important decisions that impact how we write and use our CSS:

  1. 首先,我们决定用 RTLCSS 项目来构建它。这为我们提供了一些强大的功能,用于在从 LTR 迁移到 RTL 时管理更改和覆盖。它还允许我们从一个代码库构建两个版本的 Bootstrap。

    ¥First, we decided to build it with the RTLCSS project. This gives us some powerful features for managing changes and overrides when moving from LTR to RTL. It also allows us to build two versions of Bootstrap from one codebase.

  2. 其次,我们重命名了一些方向类,以采用更合理的属性方法。感谢我们的 Flex 工具,你们中的大多数人已经与逻辑属性进行了交互 - 它们替换了 leftright 等方向属性,而有利于 startend。这使得类名和值适合 LTR 和 RTL,而无需任何开销。

    ¥Second, we’ve renamed a handful of directional classes to adopt a logical properties approach. Most of you have already interacted with logical properties thanks to our flex utilities—they replace direction properties like left and right in favor start and end. That makes the class names and values appropriate for LTR and RTL without any overhead.

例如,使用 .ms-3 代替 margin-left.ml-3

¥For example, instead of .ml-3 for margin-left, use .ms-3.

不过,通过我们的源 Sass 或编译后的 CSS 使用 RTL 应该与我们默认的 LTR 不会有太大区别。

¥Working with RTL, through our source Sass or compiled CSS, shouldn’t be much different from our default LTR though.

从源头定制

¥Customize from source

对于 customization,首选方法是利用变量、映射和混合宏。得益于 RTLCSS 的工作原理,即使它是从编译文件进行后处理的,此方法也同样适用于 RTL。

¥When it comes to customization, the preferred way is to take advantage of variables, maps, and mixins. This approach works the same for RTL, even if it’s post-processed from the compiled files, thanks to how RTLCSS works.

自定义 RTL 值

¥Custom RTL values

使用 RTLCSS 值指令,你可以使变量为 RTL 输出不同的值。例如,要减少整个代码库中 $font-weight-bold 的权重,你可以使用 /*rtl: {value}*/ 语法:

¥Using RTLCSS value directives, you can make a variable output a different value for RTL. For example, to decrease the weight for $font-weight-bold throughout the codebase, you may use the /*rtl: {value}*/ syntax:

$font-weight-bold: 700 #{/* rtl:600 */} !default;

对于我们的默认 CSS 和 RTL CSS,它将输出以下内容:

¥Which would output to the following for our default CSS and RTL CSS:

/* bootstrap.css */
dt {
  font-weight: 700 /* rtl:600 */;
}

/* bootstrap.rtl.css */
dt {
  font-weight: 600;
}

替代字体堆栈

¥Alternative font stack

如果你使用自定义字体,请注意并非所有字体都支持非拉丁字母。要从泛欧系列切换到阿拉伯系列,你可能需要在字体堆栈中使用 /*rtl:insert: {value}*/ 来修改字体系列的名称。

¥In the case you’re using a custom font, be aware that not all fonts support the non-Latin alphabet. To switch from Pan-European to Arabic family, you may need to use /*rtl:insert: {value}*/ in your font stack to modify the names of font families.

例如,要从 LTR 的 Helvetica Neue 字体切换到 RTL 的 Helvetica Neue Arabic 字体,你的 Sass 代码可能如下所示:

¥For example, to switch from Helvetica Neue font for LTR to Helvetica Neue Arabic for RTL, your Sass code could look like this:

$font-family-sans-serif:
  Helvetica Neue #{"/* rtl:insert:Arabic */"},
  // Cross-platform generic font family (default user interface font)
  system-ui,
  // Safari for macOS and iOS (San Francisco)
  -apple-system,
  // Chrome < 56 for macOS (San Francisco)
  BlinkMacSystemFont,
  // Windows
  "Segoe UI",
  // Android
  Roboto,
  // Basic web fallback
  Arial,
  // Linux
  "Noto Sans",
  // Sans serif fallback
  sans-serif,
  // Emoji fonts
  "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default;

同时进行 LTR 和 RTL

¥LTR and RTL at the same time

需要在同一页面上同时使用 LTR 和 RTL 吗?感谢 RTLCSS 字符串映射,这非常简单。用一个类封装你的 @import,并为 RTLCSS 设置自定义重命名规则:

¥Need both LTR and RTL on the same page? Thanks to RTLCSS String Maps, this is pretty straightforward. Wrap your @imports with a class, and set a custom rename rule for RTLCSS:

/* rtl:begin:options: {
  "autoRename": true,
  "stringMap":[ {
    "name": "ltr-rtl",
    "priority": 100,
    "search": ["ltr"],
    "replace": ["rtl"],
    "options": {
      "scope": "*",
      "ignoreCase": false
    }
  } ]
} */
.ltr {
  @import "../node_modules/bootstrap/scss/bootstrap";
}
/*rtl:end:options*/

运行 Sass 然后运行 RTLCSS 后,CSS 文件中的每个选择器将在前面加上 .ltr,对于 RTL 文件则加上 .rtl。现在,你可以在同一个页面上使用这两个文件,并且只需在组件封装器中使用 .ltr.rtl 即可使用其中一个方向。

¥After running Sass then RTLCSS, each selector in your CSS files will be prepended by .ltr, and .rtl for RTL files. Now you’re able to use both files on the same page, and simply use .ltr or .rtl on your components wrappers to use one or the other direction.

使用 LTR 和 RTL 组合实现时需要考虑的极端情况和已知限制:

¥Edge cases and known limitations to consider when working with a combined LTR and RTL implementation:

  1. 切换 .ltr.rtl 时,请确保相应地添加 dirlang 属性。

    ¥When switching .ltr and .rtl, make sure you add dir and lang attributes accordingly.

  2. 同时加载这两个文件可能会造成真正的性能瓶颈:考虑使用一些 optimization,或许也可以尝试使用 异步加载其中一个文件

    ¥Loading both files can be a real performance bottleneck: consider some optimization, and maybe try to load one of those files asynchronously.

  3. 以这种方式嵌套样式将导致我们的 form-validation-state() 混合宏无法按预期工作,因此需要你自行进行一些调整。参见 #31223

    ¥Nesting styles this way will prevent our form-validation-state() mixin from working as intended, thus require you tweak it a bit by yourself. See #31223.

你是否想要自动化此过程并解决涉及单个样式表中两个方向的多个边缘情况?然后,考虑使用 PostCSS RTLCSS 作为 PostCSS 插件来处理你的源文件。PostCSS RTLCSS 在幕后使用 RTLCSS 来管理方向翻转过程,但它将翻转的声明分离为具有不同 LTR 和 RTL 前缀的规则,这允许你在同一样式表文件中拥有两个方向。通过这样做,你可以通过简单地更改页面的 dir(或者甚至通过修改特定的类,如果你相应地配置插件)来在 LTR 和 RTL 方向之间切换。

¥Do you want to automate this process and address several edge cases involving both directions within a single stylesheet? Then, consider using PostCSS RTLCSS as a PostCSS plugin to process your source files. PostCSS RTLCSS uses RTLCSS behind the scenes to manage the direction flipping process, but it separates the flipped declarations into rules with a different prefix for LTR and RTL, something that allows you to have both directions within the same stylesheet file. By doing this, you can switch between LTR and RTL orientations by simply changing the dir of the page (or even by modifying a specific class if you configure the plugin accordingly).

使用 PostCSS RTLCSS 构建 LTR 和 RTL 组合实现时需要考虑的重要事项:

¥Important things to take into account when using PostCSS RTLCSS to build a combined LTR and RTL implementation:

  1. 建议你将 dir 属性添加到 html 元素。这样,当你更改方向时,整个页面都会受到影响。此外,请确保相应地添加 lang 属性。

    ¥It is recommended that you add the dir attribute to the html element. This way, the entire page will be affected when you change the direction. Also, make sure you add the lang attribute accordingly.

  2. 使用一个包含两个方向的 bundle 会增加最终样式表的大小(平均增加 20%-30%):考虑一些 optimization

    ¥Having a single bundle with both directions will increase the size of the final stylesheet (on average, by 20%-30%): consider some optimization.

  3. 请注意,PostCSS RTLCSS 与 /* rtl:remove */ 指令不兼容,因为它不会移除任何 CSS 规则。你应该分别用 /* rtl:freeze *//* rtl:begin:freeze *//* rtl:end:freeze */ 指令替换 /* rtl:remove *//* rtl:begin:remove *//* rtl:end:remove */ 指令。这些指令会将当前方向作为目标规则或声明的前缀,但不会创建 RTL 对应项(与 RTLCSS 中的 remove 指令效果相同)。

    ¥Take into account that PostCSS RTLCSS is not compatible with /* rtl:remove */ directives because it doesn’t remove any CSS rule. You should replace your /* rtl:remove */, /* rtl:begin:remove */ and /* rtl:end:remove */ directives with /* rtl:freeze */, /* rtl:begin:freeze */ and /* rtl:end:freeze */ directives respectively. These directives will prefix the targeted rules or declarations with the current direction but will not create an RTL counterpart (same result as the remove ones in RTLCSS).

面包屑案例

¥The breadcrumb case

面包屑分隔符 是唯一需要其自身全新变量(即 $breadcrumb-divider-flipped)的情况,默认为 $breadcrumb-divider

¥The breadcrumb separator is the only case requiring its own brand-new variable— namely $breadcrumb-divider-flipped —defaulting to $breadcrumb-divider.

其他资源

¥Additional resources