{"id":6658,"date":"2025-07-31T13:41:01","date_gmt":"2025-07-31T18:41:01","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=6658"},"modified":"2025-07-31T13:41:02","modified_gmt":"2025-07-31T18:41:02","slug":"should-we-never-use-non-logical-properties","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/should-we-never-use-non-logical-properties\/","title":{"rendered":"Should we NEVER use non-logical properties?"},"content":{"rendered":"\n<p>CSS has <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/CSS_logical_properties_and_values\">&#8220;logical properties&#8221;<\/a> which have the unique ability to follow the flow of language. You might be working on an website in English, which is left-to-right and top-to-bottom, but other languages might flip either or both of those. In English, we know what <code>margin-right<\/code> does, but can quickly become the wrong choice if the direction of a web page is flipped, <a href=\"https:\/\/frontendmasters.com\/blog\/to-flip-or-not-to-flip\/\">perhaps during translation<\/a>.<\/p>\n\n\n\n<p>So instead of <code>margin-right<\/code>, more and more CSS authors are writing <code>margin-inline-end<\/code>, which matches our intention better. Should the flow of the site change, our intention, and the design, holds. <\/p>\n\n\n\n<p>You probably already knew that. <\/p>\n\n\n\n<p>So, what, then?<\/p>\n\n\n\n<p>Are we to absolutely never use a &#8220;physical&#8221; property again, like <code>margin-right<\/code>? Knowing that there is a better property available? <\/p>\n\n\n\n<p>My take: <strong>yes, just use logical properties all the time. <\/strong><\/p>\n\n\n\n<p>If you need an answer with zero nuance, there it is. You&#8217;ll be better off and make better websites for people if you just entirely switch as often as you can. <\/p>\n\n\n\n<p>There is some nuance, though, and plenty of pushback. <a href=\"https:\/\/nerdy.dev\/is-it-time-to-throw-out-physical-properties#:~:text=I%20don%27t%20write%20websites%20that%20are%20translated%20into%20different%20languages\">People say things like<\/a>:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>No, why should I unlearn the old ways? I don&#8217;t write websites that are translated into different languages with different reading directions.<\/p>\n<\/blockquote>\n\n\n\n<p>That&#8217;s not a reasonable opinion when you can just straight up see that <a href=\"https:\/\/chromewebstore.google.com\/detail\/google-translate\/aapbdbdomjkkjkaonfhkkikfgjllcleb\">Google Translate has 29 million users<\/a>, and you don&#8217;t even need it installed to translate sites as it&#8217;s just built into Chrome and other browsers. Your website <em>is<\/em> being translated. Whether flow direction is flipped during that translation is less clear (it appears that is <a href=\"https:\/\/front-end.social\/@chriscoyier\/114501050997950209\"><em>not<\/em> a default behavior<\/a> of Google Translate, but sites may do it anyway, and other translators might work differently.)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">So, when should you <em>not<\/em> use logical properties?<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">When you can&#8217;t<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Media queries.<\/strong> There is <code>@media (width &lt; 30rem) { }<\/code> but not  <code>@media (inline-size &lt; 30rem) { }<\/code><\/li>\n\n\n\n<li><strong>Transform function.<\/strong> There is <code>translateX()<\/code> but not <code>translateInline()<\/code>. This is similar with the <code>Y<\/code> version, and across other functions like <code>scaleX<\/code> and <code>skewX<\/code>. <\/li>\n\n\n\n<li><strong>Background position.<\/strong> There is <code>background-position-x<\/code> but not <code>background-position-inline<\/code>. (Likewise with <code>y<\/code>)<\/li>\n\n\n\n<li><strong>Gradients.<\/strong> There is <code>linear-gradient(to top, black, white)<\/code> but not <code>linear-gradient(to block start, black, white);<\/code><\/li>\n<\/ul>\n\n\n\n<p>It&#8217;s just missing a few properties, as sometimes it was clearly thought of. We have <code><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/overflow-inline\">overflow-inline<\/a><\/code>, for example, as a logical replacement of <code>overflow-x<\/code>. Jeremy Keith <a href=\"https:\/\/adactio.com\/journal\/19457\">notes some others<\/a>, like how the JavaScript API <code>getBoundingClientRect<\/code> doesn&#8217;t return things in logical values.<\/p>\n\n\n\n<p>When you can&#8217;t, but you actually need to, you&#8217;ll need to check the directions to handle it likely.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.hero-graphic<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">background<\/span>: \n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-built_in\">url<\/span>(hero.jpg),\n<\/span><\/span><mark class='shcb-loc'><span>    <span class=\"hljs-built_in\">linear-gradient<\/span>(to top, black, transparent);\n<\/span><\/mark><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">color<\/span>: white;\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-attribute\">place-items<\/span>: end start;\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-selector-class\">.vertical-writing-mode<\/span> <span class=\"hljs-selector-class\">.hero-graphic<\/span> {\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-attribute\">background<\/span>: \n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-built_in\">url<\/span>(hero.jpg),\n<\/span><\/span><mark class='shcb-loc'><span>    <span class=\"hljs-built_in\">linear-gradient<\/span>(to left, black, transparent);\n<\/span><\/mark><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">When it doesn&#8217;t make sense<\/h3>\n\n\n\n<p>I always think of images in this cateogry. Just because text starts flowing top-to-bottom in some languages, doesn&#8217;t mean we flip images 90 degrees. Like if there is an image in the middle of a blog post in Japanese, the image is still shown as-taken.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"598\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/japanese-blog-post.png?resize=1024%2C598&#038;ssl=1\" alt=\"\" class=\"wp-image-6668\" style=\"width:721px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/japanese-blog-post.png?resize=1024%2C598&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/japanese-blog-post.png?resize=300%2C175&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/japanese-blog-post.png?resize=768%2C448&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/japanese-blog-post.png?resize=1536%2C897&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/japanese-blog-post.png?w=2028&amp;ssl=1 2028w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n<\/div>\n\n\n<p>So if we&#8217;re setting the size of that image, we&#8217;d still use <code>width<\/code> to constrain it not <code>inline-size<\/code>, probably. Although it might make sense to <em>constrain<\/em> the maximums in <em>both<\/em> directions, in which case using logical properties or not is fine.<\/p>\n\n\n\n<p><a href=\"https:\/\/blog.kizu.dev\/logical-props\/\">Roma Komarov says<\/a>:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>While it&nbsp;might be&nbsp;a&nbsp;good idea to&nbsp;approach CSS with logical keywords first, there are cases where we&nbsp;could want to&nbsp;use physical properties and values. For example, when we&nbsp;want to&nbsp;match something with the positions on&nbsp;an&nbsp;image, which won\u2019t change based on&nbsp;the writing mode.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">When you&#8217;re matching the intent<\/h3>\n\n\n\n<p>Miriam once wrote:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>It\u2019s not&nbsp;<em>bad<\/em>&nbsp;to use the physical properties sometimes, when they best express the design intent, but they shouldn\u2019t be encouraged as the default choice.<\/p>\n<cite><a href=\"https:\/\/www.miriamsuzanne.com\/2022\/09\/16\/tpac-logical\/\">A long-term plan for logical properties?<\/a><\/cite><\/blockquote>\n\n\n\n<p>The intent could be, for example, place this chat widget on the bottom right of the page. The language perhaps doesn&#8217;t matter here, it&#8217;s adhering to where feels right in the browser and has become something of a defacto standard.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"738\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/Screenshot-2025-07-31-at-7.52.20-AM.png?resize=1024%2C738&#038;ssl=1\" alt=\"\" class=\"wp-image-6669\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/Screenshot-2025-07-31-at-7.52.20-AM-scaled.png?resize=1024%2C738&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/Screenshot-2025-07-31-at-7.52.20-AM-scaled.png?resize=300%2C216&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/Screenshot-2025-07-31-at-7.52.20-AM-scaled.png?resize=768%2C553&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/Screenshot-2025-07-31-at-7.52.20-AM-scaled.png?resize=1536%2C1107&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/Screenshot-2025-07-31-at-7.52.20-AM-scaled.png?resize=2048%2C1476&amp;ssl=1 2048w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>When positioning that, we could set the <code>bottom<\/code> and <code>right<\/code> values, as they match the intent, rather than swapping them out for <code>inset-block-end<\/code> and <code>inset-inline-end<\/code>. <\/p>\n\n\n\n<p>This <em>may<\/em> be the case when you&#8217;re doing things like anchor positioning and fallbacks, where the physical nature of the browser window might be of more consequence than the language direction.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Cheat Sheet<\/h2>\n\n\n\n<p>From Adrian Roselli:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_QXKpxG\" src=\"\/\/codepen.io\/anon\/embed\/QXKpxG?height=450&amp;theme-id=1&amp;slug-hash=QXKpxG&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed QXKpxG\" title=\"CodePen Embed QXKpxG\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Best bet: just always use them.<\/p>\n<p>More nuanced take: there is a few situations where using the physical property is still releavant.<\/p>\n","protected":false},"author":1,"featured_media":6671,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[7,347],"class_list":["post-6658","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-css","tag-logical-properties"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/07\/logical.jpg?fit=2000%2C1400&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/6658","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=6658"}],"version-history":[{"count":7,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/6658\/revisions"}],"predecessor-version":[{"id":6672,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/6658\/revisions\/6672"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/6671"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=6658"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=6658"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=6658"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}