bootstrap icon indicating copy to clipboard operation
bootstrap copied to clipboard

Switch to logical properties to handle LTR/RTL at once

Open BSarmady opened this issue 3 years ago • 4 comments

Prerequisites

Proposal

Referring to this comment and this SO answer, and CanIUse inset-inline-end and others, it seems these following properties are supported in all major browsers (or green?) since mid 2020

inset-inline-start (in place of left property) inset-inline-end (in place of right property) margin-inline-start (in place of margin-left property) margin-inline-end (in place of margin-right property) margin-inline (in place of margin shorthand property) padding-inline-start (in place of padding-left property) padding-inline-end (in place of padding-right property) padding-inline (in place of padding shorthand property) text-align: start; (in place of left value) text-align: end; (in place of right value) float: inline-start; (in place of left value) float: inline-end; (in place of right value)

following styles are still using left and right me-0 ... 'me-auto', ms-0 ... ms-auto, .start ... .start-100 .end ... end-100

however using above mentioned attribute and properties will allow easier transition between LTR and RTL

so instead of LTR .start-0 { left: 0 !important; } RTL .start-0 { right: 0 !important; }

We can have just .start-0 { inset-inline-start: 0 !important; }

and so on.

Currently I'm testing these transitions with following html, which allows me immediate transition between RTL and LTR

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <link rel="stylesheet" href="bootstrap-5.3.0/bootstrap.css">
    <link rel="stylesheet" href="this/main.css">
    <script src="jquery.1.11.3/jquery.min.js"></script>
    <script src="bootstrap-5.3.0/bootstrap.bundle.js"></script>
    <script>
        $(function () {
            const $html = $('html');
            if (localStorage.getItem('dir') === 'rtl') {
                $html.attr('dir', 'rtl');
            } else {
                $html.removeAttr('dir')
            }
            $('#btnDir').click(function () {
                if ($html.attr('dir') === 'rtl') {
                    $html.removeAttr('dir');
                    localStorage.removeItem('dir')
                } else {
                    $html.attr('dir', 'rtl');
                    localStorage.setItem('dir', 'rtl')
                }
            });
        })
    </script>
</head>
<body>
    <input type="button" id="btnDir" class="btn btn-primary" value="            direction            ">
    <!-- Elements being tested below-->
    <div class="toast-container p-3 bottom-0 end-0" aria-live="polite" aria-atomic="true">
        <div class="toast show text-bg-danger" role="alert" aria-live="assertive" aria-atomic="true">
            <div class="toast-header">
                <strong class="me-auto">Toast-Header</strong>
                <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
            </div>
            <div class="toast-body">Toast Body</div>
        </div>
        <div class="toast text-bg-danger border-0 show" role="alert" aria-live="assertive" aria-atomic="true">
            <div class="d-flex">
                <div class="toast-body">
                    Hello, world! This is a toast message.
                </div>
                <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
            </div>
        </div>
        <div class="toast text-bg-primary border-0 show" role="alert" aria-live="assertive" aria-atomic="true">
            <div class="d-flex">
                <div class="toast-body">Toast Body</div>
                <button type="button" class="btn-close btn-close-white m-auto ms-auto me-2" data-bs-dismiss="toast" aria-label="Close"></button>
            </div>
        </div>
    </div>
</body>
</html>

Content of main.css is something like following (obviously for these to work I need to comment their counter part in bootstrap.css)

.text-start{ text-align:start !important; }
.text-end{ text-align:end !important; }

.me-0{ margin-inline-end:0 !important }
.me-1{ margin-inline-end:0.25rem !important }
.me-2{ margin-inline-end:0.5rem !important }
.me-3{ margin-inline-end:1rem !important }
.me-4{ margin-inline-end:1.5rem !important }
.me-5{ margin-inline-end:3rem !important }
.me-auto{ margin-inline-end:auto !important }

.start-0{ inset-inline-start:0 !important; }
.start-50{ inset-inline-start:50% !important;}
.start-100{ inset-inline-start:100% !important;}

.end-0{ inset-inline-end:0 !important; }
.end-50{ inset-inline-end:50% !important;}
.end-100{ inset-inline-end:100% !important;}

.toast-header .btn-close {
    margin-inline-end: calc(-0.5 * var(--bs-toast-padding-x));
    margin-inline-start: var(--bs-toast-padding-x);
}

Motivation and context

I think it allows transition from having two separate CSS for LTR and RTL to one single file. and in case in future you want to support top to bottom languages ;)

BSarmady avatar Feb 08 '23 10:02 BSarmady

This has been considered 3 years ago while implementing RTL for v5 (see #30918). Support was still short at that time, but switching to logical properties should be one of the main move coming in V6.

I'm tagging this for v6 as I noticed there's currently no dedicated issue!

ffoodd avatar Feb 08 '23 11:02 ffoodd

Or what would have made more sense is keep the selector and change the property, so while in LTR, design for LTR, and it will magically flip on RTL

text-left { text-align: start}
text-right {text-align: end}

I really expected (hoped) for this, don't know why you went for the extreme of renaming selectors, but keeping the properties

text-start {text-align: left}

why?

ayyash avatar Feb 21 '24 18:02 ayyash

@ffoodd is this still something the team is open to changing for v6? I don't see it listed in #41380

At this point, CSS Logical Properties have been supported in all major browsers in Baseline since September 2021, so it should be overwhelmingly supported:

https://caniuse.com/css-logical-props

Removing the RTLCSS dependency would streamline our dependencies.

NateRadebaugh avatar May 06 '25 11:05 NateRadebaugh

IMHO, I'd say yes ! For now, @mdo started to work on v6 with specific topics but I think logical properties are the way to go.

ffoodd avatar May 06 '25 12:05 ffoodd