Skip to content

Negative numbers in RTL

Learn why minus signs move in Arabic interfaces and how to preserve negative values, format them clearly, and test balances and temperatures.

By , Founder of Ritla

Guide14 min read

A refrigerated warehouse console reports a net inventory movement of -2764. Inside its Arabic summary, the visible sequence becomes 2764-. The minus has not disappeared, and the digits have not reversed. The sign and the number are participating in the paragraph's right-to-left reading order.

That appearance alone does not establish a defect. The reader needs to identify the negative value under the interface's chosen numeric convention. A missing sign, a clipped sign and a sign rendered according to a different convention are separate problems. Changing the stored value to make one screenshot look familiar can create all three elsewhere.

Start with the number's meaning, then choose and test its presentation. The warehouse's stock movements, account balances and below-zero temperatures all need a visible sign, but a negative value does not mean the same thing in each field.

A leading minus moves even without an Arabic label#

These two paragraphs contain the same stored value:

html
<p lang="ar" dir="rtl">صافي حركة المخزون: -2764</p><p dir="rtl">-2764</p>

Both display the numeric sequence as 2764-. The bare value still has a trailing visual minus in an RTL paragraph. Removing the Arabic label therefore does not demonstrate a fix.

The leading ASCII hyphen-minus does not establish an independent LTR phrase with the digits. Its resolved position depends on bidi context. The Unicode Bidirectional Algorithm describes the distinction between stored character order and display order.

The display patterns used here were measured in Chromium 151 on September 24, 2026. Firefox and Safari were not included in those measurements, so verify the fixtures in your supported browsers.

Before calling the right-hand minus wrong, state the expected reading. An RTL numeric presentation can place the sign where the reader encounters it from the right. An interface that has explicitly adopted an LTR technical numeric convention expects a leading sign on the left. Review the selected convention with an Arabic reader instead of treating English visual familiarity as the acceptance criterion.

In either case, the source number remains negative. Do not transpose its characters or store a trailing-minus string in response to this rendering.

Separate a sign error from a direction error#

Compare the API value, the element's text and the visible result. That sequence distinguishes several failures that otherwise attract the same “negative numbers are backwards” report.

ObservationWhat to investigate
API value is negative, text has no negative indicatorFormatter, absolute-value conversion or template logic
Text contains the intended sign, but it appears at another endDirectional context and the approved numeric convention
Full text is correct, but the sign is outside the visible boxClipping, truncation or overlap
Display is negative, but sorting or submission treats it as positiveData conversion or parsing of a display string

A sign appearing on the right is different from a positive number. An implementation that drops the sign to avoid a bidi discussion changes the value's meaning.

Also distinguish a signed quantity from subtraction. The inventory movement is one negative number. An expression containing two operands and a minus operator is a different unit of content. Do not copy a numeric-value fix onto an entire Arabic explanation or assume a hyphen in an identifier is a mathematical sign.

If the value is positive in the API, stop adjusting direction. Resolve the calculation or mapping first. If the raw value is correct, preserve it while changing only the display boundary or formatter responsible for the presentation.

Keep a known LTR signed value together#

If the warehouse deliberately uses Western digits and a leading minus for technical quantities, declare that direction on the complete value:

Problem under that convention

html
<p lang="ar" dir="rtl">  صافي حركة المخزون: <span>-2764</span></p>

The plain span isolates nothing. The value still displays as 2764-.

Implementation of the LTR convention

html
<p lang="ar" dir="rtl">  صافي حركة المخزون: <span dir="ltr">-2764</span></p>

The isolated value displays as -2764. The Arabic label retains its own direction. The sign and all digits belong inside the same span; do not put the minus in a separate badge or leave it outside the wrapper.

A bdi around this plain Western-digit value also resolves LTR in the measured behavior because it contains no strong letters. An explicit direction is clearer when the component has a known LTR contract. Locale-formatted output can contain directional characters, so it should not be assumed to behave like this plain literal.

The W3C inline bidi guidance recommends wrapping a complete opposite-direction phrase. Here that phrase is the signed number, not the whole Arabic summary. Continue with bidi isolation in HTML if a shared component needs a broader direction policy.

Explain what the negative value means#

The warehouse summary should tell the reader that a negative movement means a net reduction in stock. A temperature below zero is not automatically a warning. An account balance can represent an amount owed or a credit depending on the product's balance convention.

Use labels that describe those meanings. A generic red number labelled only “balance” leaves too much interpretation to the reader. Adding a word that means decrease, credit or below zero can clarify the field without changing the numeric value.

Colour can reinforce the meaning, but should not carry it alone. W3C's guidance on use of colour explains the need for another visible cue when colour communicates information. Keep the sign and suitable wording available when colours are unavailable or hard to distinguish.

Do not replace the minus with a downward arrow and assume the value is now clear. A downward arrow could describe a trend, while the number itself may be a level below zero. Likewise, an expected negative freezer temperature should not inherit an error style just because a generic numeric component classifies every negative value as bad.

Review the sign's arithmetic meaning and the status label together. The number can be formatted correctly while the accompanying interpretation is wrong.

Update sign and meaning from the same number#

This component implements the warehouse's LTR technical convention, with two decimal places for mass movements. Its meaning label distinguishes reduction, increase and no net change:

html
<div lang="ar" dir="rtl">  <p>    صافي حركة المخزون:    <span id="movement-value" dir="ltr"></span> كيلوغرام  </p>  <p id="movement-meaning"></p></div>

Run this JavaScript after the markup:

js
const movementFormat = new Intl.NumberFormat("en-GB", {  numberingSystem: "latn",  useGrouping: false,  minimumFractionDigits: 2,  maximumFractionDigits: 2}); function renderMovement(value) {  if (!Number.isFinite(value)) {    throw new TypeError("Expected a finite inventory movement");  }   const displayValue = Object.is(value, -0) ? 0 : value;  const state = displayValue < 0 ? "negative"    : displayValue > 0 ? "positive" : "zero";  const meanings = {    negative: "صافي نقص",    positive: "صافي زيادة",    zero: "لا تغير صافٍ"  };   document.getElementById("movement-value").textContent =    movementFormat.format(displayValue);  document.getElementById("movement-meaning").textContent = meanings[state];} renderMovement(-2764);

Both outputs derive from the same numeric input. Switching from a negative to a positive movement replaces the whole formatted value, so an independently rendered minus cannot remain behind. The code also has an explicit policy for actual negative zero, discussed below.

Insert formatted values as text, using textContent or the equivalent escaped framework binding. Retain the value wrapper during updates. Do not replace the entire paragraph with an unisolated string after a successful initial render.

This formatter is for a selected technical convention. For a localized Arabic numeric convention, choose an Arabic formatter and review its complete output rather than retaining the English formatter and swapping digit characters manually.

Inspect the Arabic formatter's actual sign representation#

Arabic number formatting can include a directional literal as well as a minus sign, digits and separators. Inspect those parts instead of inferring their sequence from a console preview:

js
const arabicMovementFormat = new Intl.NumberFormat("ar-EG", {  numberingSystem: "arab",  minimumFractionDigits: 2,  maximumFractionDigits: 2,  signDisplay: "auto"}); console.table(arabicMovementFormat.formatToParts(-2764).map(part => ({  type: part.type,  codePoints: Array.from(part.value, character =>    "U+" + character.codePointAt(0)      .toString(16).toUpperCase().padStart(4, "0")  ).join(" ")})));

In a string inspection using Node 24.16.0 with ICU 78.3, this produced a literal containing U+061C, ARABIC LETTER MARK, before a minusSign part containing U+002D. Arabic-Indic digits and number separators followed. This establishes the generated character sequence, not the visual result in an untested browser.

Preserve the complete formatted string. Removing the literal because it is invisible can change its display in surrounding text. MDN documents that formatted numbers can include bidi controls and non-breaking spaces.

If you style the sign separately with formatToParts(), retain every part in its original sequence inside one value boundary. Do not put the sign in a reversed flex row or append it after the digits yourself.

Locale, numbering system and precision are product choices. Set them deliberately and inspect resolvedOptions() on the server and client when both render numbers. Do not assume every Arabic locale uses the same defaults, or that declaring the page's language configures JavaScript number formatting.

A different minus glyph does not replace direction handling#

The character - is U+002D, HYPHEN-MINUS. The character − is U+2212, MINUS SIGN. They can have different widths and appearances in a font, but choosing the mathematical glyph is not a declaration that the value should be LTR.

Keep character choice separate from directional boundaries. Do not substitute a dash-like character merely because one screenshot places it more conveniently. If a typography policy changes the minus glyph, test that glyph with the actual digits, font and surrounding text.

Do not infer the sign by checking whether a formatted string begins with the ASCII hyphen. The Arabic formatter inspection already shows why that fails: a directional literal can precede the minusSign part. Other conventions can represent a negative amount differently.

Use the raw numeric value to determine whether it is negative. Use formatter parts to identify a displayed sign when styling or diagnostics require that information. Neither operation needs to parse the visible glyph's physical position.

If imported data uses a Unicode minus in a textual numeric field, handle it under that field's documented parsing contract. Do not assume a browser numeric parser accepts every character that looks like a minus.

Negative zero and rounded zero need separate decisions#

JavaScript distinguishes negative zero from positive zero. Object.is(value, -0) detects actual negative zero, unlike an ordinary equality comparison. MDN's Object.is() reference documents that distinction.

The warehouse renderer normalizes actual negative zero for presentation. That is an application decision: it treats exact zero movement as no net change. The code does not mutate the measurement record.

A small negative value that rounds to zero is different. With two decimal places, -0.0008 can produce the display -0.00 under the technical formatter. The raw number is still negative, and Object.is(-0.0008, -0) is false. Normalizing actual negative zero does not address this case.

Decide whether the panel should retain the signed rounded zero, show more precision, or describe the movement as smaller than its display resolution. Do not silently strip the minus while leaving a label that says the movement is negative. Conversely, do not classify a small measured movement as mathematically zero just because the summary rounds it away.

signDisplay controls which signs a formatter emits; it is not a general fix for bidi layout. In particular, hiding signs globally would conceal actual negatives. MDN's number-format options cover sign and precision settings.

Keep alarm or reconciliation comparisons on the raw measurement under the product's measurement policy. Changing the displayed precision should not independently change the arithmetic interpretation of the same reading.

A subtraction expression needs its own boundary#

An inventory reconciliation detail can explain how the negative movement was calculated. If that detail uses a deliberately LTR technical expression, wrap the complete expression:

html
<p lang="ar" dir="rtl">  حساب الفرق: <span dir="ltr">8126 - 10890 = -2764</span></p>

The first minus separates two operands. The second is the sign of the result. Treating both marks as interchangeable decorative characters loses the expression's structure. Check the arithmetic against the underlying quantities as well as reviewing the displayed sequence.

Do not isolate each digit group independently and leave the operators in the Arabic paragraph. The intended unit here includes operands, operators and result. For this selected expression convention, one boundary describes that whole unit more clearly than a collection of unrelated number spans.

This recommendation does not require every Arabic mathematical expression to adopt the same notation. It describes a product that has chosen an LTR technical calculation and needs to preserve it within Arabic explanatory copy. If the product uses another reviewed mathematical convention, model and test that convention explicitly.

Do not feed the expression string into a numeric formatter. Format its numeric operands under the chosen policy, then compose the expression with its own structure. Likewise, a parser for one signed input value should not accept arbitrary subtraction syntax just because both contain a minus character.

A display test should confirm which quantity is subtracted from which. A visually plausible expression with swapped operands computes the opposite sign, even if every minus remains visible.

Temperatures need their unit and scale#

A negative freezer reading is a signed measurement, not a stock reduction. For an explicitly LTR Celsius display, protect the complete measurement:

html
<p lang="ar" dir="rtl">  درجة حرارة الغرفة: <span dir="ltr">-18.375 °C</span></p>

The wrapper contains the sign, digits and unit. The Arabic label stays outside. Test that exact measurement with the production font and layout rather than extrapolating every mixed unit string from the plain integer example.

If the product uses a localized unit formatter, preserve its complete result and test that convention instead. Do not apply the label for one temperature scale to a numeric reading from another. A perfectly visible minus cannot repair the wrong scale or a stale sensor association.

Ranges require two signed endpoints. For a freezer setting, label the lower and upper limits clearly and test both against the underlying numeric bounds. Avoid joining several minus signs and numbers into an unreviewed string where a reader must guess which mark is a sign and which separates the endpoints.

Do not colour the reading red solely because it is below zero. Its status comes from the configured range and measurement context. Keep the numeric sign, the scale and the status explanation available independently.

Account balances can use accounting notation#

A warehouse account panel can represent a negative monetary amount with a minus or with accounting parentheses, depending on its selected locale and formatting policy. No visible minus does not automatically mean a lost sign if another approved negative notation is present.

For example, this formatter requests an English accounting presentation:

js
const accountingAmount = new Intl.NumberFormat("en-GB", {  style: "currency",  currency: "GBP",  currencySign: "accounting"}); console.log(accountingAmount.format(-2764)); // "(£2,764.00)"

Do not assume every Arabic locale will produce those same parentheses. Inspect the formatter for the actual market and currency. If an LTR accounting string is embedded in Arabic, keep its complete amount, including parentheses and currency, inside its value boundary.

The surrounding label still needs to define what a negative balance means in that product. It might represent credit rather than an amount due. Do not change that interpretation because the amount is styled red, and do not convert it to an absolute value merely to simplify the display.

Keep currency precision and negative notation in the currency formatter rather than applying the stock-movement formatter to money. The two fields share sign handling concerns, but their units and formatting contracts differ.

Preserve signed input through editing and submission#

A correction form needs to accept the negative values its domain permits. If the user is entering a signed mass adjustment, an unrelated nonnegative minimum can block the intended correction even when the display component is correct.

html
<form lang="ar" dir="rtl">  <label for="mass-adjustment">تعديل الكتلة بالكيلوغرام</label>  <input id="mass-adjustment" name="massAdjustment"         type="number" dir="ltr" step="0.01" value="-2764">  <button type="submit">تطبيق التعديل</button></form>

This example intentionally uses an LTR numeric editing convention and permits fractional adjustments with the stated step. Your server must apply the field's actual validation rules. MDN's number-input reference explains numeric input, step and range constraints.

Test typing a minus, pasting a signed value, editing across zero and submitting. Number-input interaction and accepted localized characters need testing in supported browsers. Do not assume this control accepts arbitrary localized formatter output containing grouping separators, units or directional literals.

If the product requires a custom localized text editor, define its parsing rules separately. Converting a formatted display string back to a number by deleting non-digits destroys the sign and can also lose decimal meaning. Preserve a parsed signed number through validation, preview and submission.

An empty input is not a zero adjustment. Treat missing input as its own validation state instead of assigning zero before the user has confirmed a value.

Diagnose clipping, context and stale sign state#

For the warehouse component, compare the numeric movement with movement-value.textContent, then inspect the actual rendered sequence. Use a code-point view or formatter parts if invisible literals make a preview ambiguous.

Inspect the value wrapper's direction, not just the page. Look for a plain span where an isolate was intended, a shared style that changes bidi behavior, or a sign rendered in a different node from the magnitude. If switching from negative to positive leaves the minus behind, trace conditional rendering before changing CSS.

At narrow widths, reveal the full value temporarily. A clipped minus can make a negative movement look positive. An ellipsis that preserves the digits but hides their negative notation is particularly misleading; the compact view needs enough room or an explicit full-value presentation.

For dense numeric columns, use matching positive and negative magnitudes when checking available space. A width approved using positive fixtures alone has not reserved room for a sign, directional literals or accounting notation. Also include the formatted number's grouping and fractional digits, since the raw measurement's character count does not describe its displayed width.

Inspect the cell and its parent separately. The value may fit inside its own span while a parent clips the edge containing the sign. Temporarily remove the parent constraint before changing the number's direction. If changing alignment merely reveals the sign at one width, it has not established that the value fits at the other supported widths.

Where comparison requires full signed values, prefer making the complete value available over shortening it to a magnitude. If a compact summary intentionally uses a shorter numeric notation, choose that notation through a formatter and retain its negative indication. Do not shorten by slicing characters from the assembled localized string.

Compare copying and display separately. Copying can return the correctly ordered negative string while the visible sign appears at another end. A screen reader check also does not establish visual order, although it remains useful for checking the value's label and interpretation.

For exports or sorting, return to the raw numeric value. A localized display string is not a portable signed-number serialization. Define whether an export carries raw numbers for calculation or formatted text for reading, and test the receiving application under that contract.

Test the whole sign transition#

Use the same movement record across the Arabic summary, detail view, correction preview and exported value. Then drive the component through negative, zero and positive states without reloading the page.

FixtureWhat it catches
Negative movement and its positive counterpartLost signs, stale sign nodes and inconsistent labels
Actual negative zeroThe chosen exact-zero presentation policy
Small negative value that rounds to zeroDisagreement between precision, sign and explanation
Below-zero temperature with its scaleUnit ownership and incorrect generic negative styling
Negative account amountCurrency-specific negative notation
Missing or non-finite measurementFabricated zeroes or accidental invalid-number display

Assert the raw value and formatter output, then review the visible sign under the approved convention. Include standalone values as well as Arabic-labelled paragraphs because a bare RTL value still exposes the leading-minus behavior.

Repeat the visual review in supported browsers and compact layouts. Test with colour removed and confirm that the sign and wording still explain the value. Keep the numerical, visual and meaning checks distinct so that a passing copy test cannot conceal a missing or misplaced sign on screen.

For punctuation at the wrong visual end, a free Ritla scan can report R024: Punctuation rendering at the wrong visual end of Arabic text. Review sign placement against the chosen numeric convention; negative-zero policy, arithmetic sign and field meaning still need the checks above. Continue with how browsers render mixed-direction text for contextual ordering or Arabic text getting cut off in CSS when a sign is present but not visible.

Checks in this guide

See what your Arabic pages are hiding

Paste a URL. Ritla renders the page on desktop and mobile, runs every check, and shows the top issues with screenshot evidence.

Scan a page freeBrowse the checks