> For the complete documentation index, see [llms.txt](https://kb.craftformswp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kb.craftformswp.com/documentation/form-building/create-form/conditions-and-logic-in-formulas.md).

# Conditions and Logic in Formulas

You can use conditions in a **Price Formula**, a **Smart Variable**, a **Conditional Variable**, or a **Dynamic Validation** expression. This page shows how to ask "is this true?" questions in plain language, and how to combine several questions into one. No coding needed.

***

### The one thing to remember <a href="#the-one-thing-to-remember" id="the-one-thing-to-remember"></a>

A condition is just a question that can only be answered **true** or **false**.

`width > 100` reads as "is width bigger than 100?" — if width is `150`, the answer is **true**. If width is `50`, the answer is **false**.

Everything on this page is built out of small true/false questions like that one, combined together.

***

### Asking a question: comparisons <a href="#asking-a-question-comparisons" id="asking-a-question-comparisons"></a>

| You want to ask…             | Type | Example           | True when…                   |
| ---------------------------- | ---- | ----------------- | ---------------------------- |
| Are these equal?             | `==` | `qty == 1`        | qty is exactly `1`           |
| Are these different?         | `!=` | `country != "NL"` | country is anything but `NL` |
| Is it bigger than?           | `>`  | `width > 100`     | width is more than `100`     |
| Is it smaller than?          | `<`  | `height < 14`     | height is less than `14`     |
| Is it bigger than or equal?  | `>=` | `qty >= 1`        | qty is `1` or more           |
| Is it smaller than or equal? | `<=` | `discount <= 50`  | discount is `50` or less     |

**Tip:** when you compare text (not a number), put it in quotes: `country == "NL"`, not `country == NL`. Field and variable names are never quoted — only the fixed text you're comparing against.

***

### Checking if a field is empty <a href="#checking-if-a-field-is-empty" id="checking-if-a-field-is-empty"></a>

This is the one you'll use the most. **`is_empty(...)`** asks "did the customer leave this blank?"

| To do this             | Type               | True when…                            |
| ---------------------- | ------------------ | ------------------------------------- |
| Field/box is empty     | `is_empty(width)`  | the customer left Width blank         |
| Field/box is filled in | `!is_empty(width)` | the customer typed something in Width |

It works for text fields, number fields, and checkboxes/selects with nothing chosen — not just plain text boxes.

***

### Combining questions: AND, OR, NOT <a href="#combining-questions-and-or-not" id="combining-questions-and-or-not"></a>

Most real-world rules need more than one question. Combine them with **`&&`** (AND), **`||`** (OR), and **`!`** (NOT).

| Symbol | Means | True when…                             |
| ------ | ----- | -------------------------------------- |
| `&&`   | AND   | **both** questions are true            |
| `\|\|` | OR    | **at least one** question is true      |
| `!`    | NOT   | flips true to false, and false to true |

Put brackets `( )` around each question when you combine several — it keeps the meaning clear, exactly like grouping in math.

| Example                                 | Reads as…                                  | True when…                                 |
| --------------------------------------- | ------------------------------------------ | ------------------------------------------ |
| `is_empty(width) && is_empty(height)`   | "Width is empty AND Height is empty"       | **both** Width and Height were left blank  |
| `is_empty(width) \|\| is_empty(height)` | "Width is empty OR Height is empty"        | **either one** (or both) was left blank    |
| `!is_empty(width)`                      | "Width is NOT empty"                       | the customer did type something into Width |
| `(width > 100) && (height > 100)`       | "Width is over 100 AND Height is over 100" | both dimensions are large                  |

**The difference between AND and OR is the most common mix-up:** use `&&` when a rule should only apply if *every* condition is true, use `||` when it should apply if *any one* of them is true.

***

### Checking against a list of options <a href="#checking-against-a-list-of-options" id="checking-against-a-list-of-options"></a>

**`in`** asks "is this one of these values?" — handy for a select or radio field, instead of writing several `==` checks joined with `||`.

| To do this               | Type                                | True when…               |
| ------------------------ | ----------------------------------- | ------------------------ |
| Value is one of a list   | `country in ["NL", "BE", "DE"]`     | country is NL, BE, or DE |
| Value is *not* in a list | `country not in ["NL", "BE", "DE"]` | country is anything else |

This does the same job as `country == "NL" || country == "BE" || country == "DE"`, just shorter and easier to read.

***

### Picking a value based on a condition <a href="#picking-a-value-based-on-a-condition" id="picking-a-value-based-on-a-condition"></a>

Sometimes you don't just want true/false — you want a *value* that depends on a condition. That's what **`condition ? valueIfTrue : valueIfFalse`** does.

| Example                              | Reads as…                                                     |
| ------------------------------------ | ------------------------------------------------------------- |
| `width > 100 ? "Large" : "Standard"` | "If width is over 100, use 'Large', otherwise use 'Standard'" |
| `is_empty(height) ? 0 : height * 2`  | "If height is empty, use 0, otherwise use height times 2"     |

This works in a Price Formula (pick a price), a Smart Variable (pick a label or number), or anywhere else formulas are allowed.

***

### Writing conditions correctly <a href="#writing-conditions-correctly" id="writing-conditions-correctly"></a>

* Put **text values in quotes**: `"NL"`, `"yes"` — not `NL`, `yes`.
* Field and variable **names are never quoted** — `width`, not `"width"`.
* Use `==` to compare, not `=` (a single `=` doesn't work in a condition).
* Wrap each question in **brackets `( )`** when combining several with `&&` / `||`, so the meaning is unambiguous.
* `&&`/`||`/`!` also have word versions — `and`/`or`/`not` — both work the same; pick whichever reads more naturally to you.

***

### Where you'll actually use this <a href="#where-youll-actually-use-this" id="where-youll-actually-use-this"></a>

**Dynamic Validation** — every field has an *Advanced* "Dynamic Validation" panel with expression boxes like **Required (expression)**, **Min Value (expression)**, **Max Value (expression)**. Whatever the expression resolves to at runtime overrides the field's static setting.

> Example: you have a "Notes" field that should only be *required* if the customer left both Width and Height blank (maybe they want to describe an odd shape instead of typing numbers). Set **Required (expression)** on the Notes field to: `is_empty(width) && is_empty(height)`

**Smart Variables / Conditional Variables** — a condition doesn't have to live directly inside a validation box. You can save it once as a Smart Variable with a clear name, then reuse that name everywhere else — including inside a Dynamic Validation expression.

> Example: create a Smart Variable called `sizing_incomplete` with the formula: `is_empty(width) || is_empty(height)` Now any other formula, validation expression, or info block can just check `sizing_incomplete` instead of repeating the full condition.

**Info Blocks** — an info block's text can show or hide a section of its message based on a variable being true or false, using `{{#variable}} ... {{/variable}}`.

> Example: reusing the `sizing_incomplete` variable from above, an info block's content could be: `{{#sizing_incomplete}}Please fill in both Width and Height before continuing.{{/sizing_incomplete}}` The reminder text only appears while the condition is true.

**Price Formula** — use `? :` to change the price itself depending on a condition, e.g. a surcharge for oversized items: `width > 100 ? (width * 2) + 15 : width * 2`. See [Doing Math in Formulas](/documentation/form-building/create-form/doing-math-in-formulas.md) for everything about the math side of formulas.

***

### Quick cheat sheet <a href="#quick-cheat-sheet" id="quick-cheat-sheet"></a>

| Symbol            | Means                                             |
| ----------------- | ------------------------------------------------- |
| `==` / `!=`       | equals / does not equal                           |
| `>` `<` `>=` `<=` | bigger / smaller (or equal)                       |
| `is_empty(x)`     | x was left blank                                  |
| `!is_empty(x)`    | x was filled in                                   |
| `&&` (or `and`)   | both must be true                                 |
| `\|\|` (or `or`)  | at least one must be true                         |
| `!` (or `not`)    | flips true/false                                  |
| `in` / `not in`   | matches one of a list / doesn't                   |
| `? :`             | if this, use that, otherwise use this other value |
