Tag: language

Let’s Create a Tiny Programming Language

By now, you are probably familiar with one or more programming languages. But have you ever wondered how you could create your own programming language? And by that, I mean:

A programming language is any set of rules that convert strings to various kinds of machine code output.

In short, a programming language is just a set of predefined rules. And to make them useful, you need something that understands those rules. And those things are compilers, interpreters, etc. So we can simply define some rules, then, to make it work, we can use any existing programming language to make a program that can understand those rules, which will be our interpreter.


A compiler converts codes into machine code that the processor can execute (e.g. C++ compiler).


An interpreter goes through the program line by line and executes each command.

Want to give it a try? Let’s create a super simple programming language together that outputs magenta-colored output in the console. We’ll call it Magenta.

Screenshot of terminal output in color magenta.
Our simple programming language creates a codes variable that contains text that gets printed to the console… in magenta, of course.

Setting up our programming language

I am going to use Node.js but you can use any language to follow along, the concept will remain the same. Let me start by creating an index.js file and set things up.

class Magenta {   constructor(codes) {     this.codes = codes   }   run() {     console.log(this.codes)   } }  // For now, we are storing codes in a string variable called `codes` // Later, we will read codes from a file const codes =  `print "hello world" print "hello again"` const magenta = new Magenta(codes) magenta.run()

What we’re doing here is declaring a class called Magenta. That class defines and initiates an object that is responsible for logging text to the console with whatever text we provide it via a codes variable. And, for the time being, we’ve defined that codes variable directly in the file with a couple of “hello” messages.

Screenshot of terminal output.
If we were to run this code we would get the text stored in codes logged in the console.

OK, now we need to create a what’s called a Lexer.

What is a Lexer?

OK, let’s talks about the English language for a second. Take the following phrase:

How are you?

Here, “How” is an adverb, “are” is a verb, and “you” is a pronoun. We also have a question mark (“?”) at the end. We can divide any sentence or phrase like this into many grammatical components in JavaScript. Another way we can distinguish these parts is to divide them into small tokens. The program that divides the text into tokens is our Lexer.

Diagram showing command going through a lexer.

Since our language is very tiny, it only has two types of tokens, each with a value:

  1. keyword
  2. string

We could’ve used a regular expression to extract tokes from the codes string but the performance will be very slow. A better approach is to loop through each character of the code string and grab tokens. So, let’s create a tokenize method in our Magenta class — which will be our Lexer.

Full code
class Magenta {   constructor(codes) {     this.codes = codes   }   tokenize() {     const length = this.codes.length     // pos keeps track of current position/index     let pos = 0     let tokens = []     const BUILT_IN_KEYWORDS = ["print"]     // allowed characters for variable/keyword     const varChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_'     while (pos < length) {       let currentChar = this.codes[pos]       // if current char is space or newline,  continue       if (currentChar === " " || currentChar === "n") {         pos++         continue       } else if (currentChar === '"') {         // if current char is " then we have a string         let res = ""         pos++         // while next char is not " or n and we are not at the end of the code         while (this.codes[pos] !== '"' && this.codes[pos] !== 'n' && pos < length) {           // adding the char to the string           res += this.codes[pos]           pos++         }         // if the loop ended because of the end of the code and we didn't find the closing "         if (this.codes[pos] !== '"') {           return {             error: `Unterminated string`           }         }         pos++         // adding the string to the tokens         tokens.push({           type: "string",           value: res         })       } else if (varChars.includes(currentChar)) { arater         let res = currentChar         pos++         // while the next char is a valid variable/keyword charater         while (varChars.includes(this.codes[pos]) && pos < length) {           // adding the char to the string           res += this.codes[pos]           pos++         }         // if the keyword is not a built in keyword         if (!BUILT_IN_KEYWORDS.includes(res)) {           return {             error: `Unexpected token $ {res}`           }         }         // adding the keyword to the tokens         tokens.push({           type: "keyword",           value: res         })       } else { // we have a invalid character in our code         return {           error: `Unexpected character $ {this.codes[pos]}`         }       }     }     // returning the tokens     return {       error: false,       tokens     }   }   run() {     const {       tokens,       error     } = this.tokenize()     if (error) {       console.log(error)       return     }     console.log(tokens)   } }

If we run this in a terminal with node index.js, we should see a list of tokens printed in the console.

Screenshot of code.
Great stuff!

Defining rules and syntaxes

We want to see if the order of our codes matches some sort of rule or syntax. But first we need to define what those rules and syntaxes are. Since our language is so tiny, it only has one simple syntax which is a print keyword followed by a string.

keyword:print string

So let’s create a parse method that loops through our tokens and see if we have a valid syntax formed. If so, it will take necessary actions.

class Magenta {   constructor(codes) {     this.codes = codes   }   tokenize(){     /* previous codes for tokenizer */   }   parse(tokens){     const len = tokens.length     let pos = 0     while(pos < len) {       const token = tokens[pos]       // if token is a print keyword       if(token.type === "keyword" && token.value === "print") {         // if the next token doesn't exist         if(!tokens[pos + 1]) {           return console.log("Unexpected end of line, expected string")         }         // check if the next token is a string         let isString = tokens[pos + 1].type === "string"         // if the next token is not a string         if(!isString) {           return console.log(`Unexpected token $ {tokens[pos + 1].type}, expected string`)         }         // if we reach this point, we have valid syntax         // so we can print the string         console.log('x1b[35m%sx1b[0m', tokens[pos + 1].value)         // we add 2 because we also check the token after print keyword         pos += 2       } else{ // if we didn't match any rules         return console.log(`Unexpected token $ {token.type}`)       }     }   }   run(){     const {tokens, error} = this.tokenize()     if(error){       console.log(error)       return     }     this.parse(tokens)   } }

And would you look at that — we already have a working language!

Screenshot of terminal output.

Okay but having codes in a string variable is not that fun. So lets put our Magenta codes in a file called code.m. That way we can keep our magenta codes separate from the compiler logic. We are using .m as file extension to indicate that this file contains code for our language.

Let’s read the code from that file:

// importing file system module const fs = require('fs') //importing path module for convenient path joining const path = require('path') class Magenta{   constructor(codes){     this.codes = codes   }   tokenize(){     /* previous codes for tokenizer */  }   parse(tokens){     /* previous codes for parse method */  }   run(){     /* previous codes for run method */   } }  // Reading code.m file // Some text editors use rn for new line instead of n, so we are removing r const codes = fs.readFileSync(path.join(__dirname, 'code.m'), 'utf8').toString().replace(/r/g, &quot;&quot;) const magenta = new Magenta(codes) magenta.run()

Go create a programming language!

And with that, we have successfully created a tiny Programming Language from scratch. See, a programming language can be as simple as something that accomplishes one specific thing. Sure, it’s unlikely that a language like Magenta here will ever be useful enough to be part of a popular framework or anything, but now you see what it takes to make one.

The sky is really the limit. If you want dive in a little deeper, try following along with this video I made going over a more advanced example. This is video I have also shown hoe you can add variables to your language also.

Let’s Create a Tiny Programming Language originally published on CSS-Tricks. You should get the newsletter.


, , , ,

HTML is Not a Programming Language?

HTML is not a programming language.

I’ve heard that sentence so many times and it’s tiring. Normally, it is followed by something like, It doesn’t have logic, or, It is not Turing complete,.so… obviously it is not a programming language. Like it’s case-closed and should be the end of the conversation.

Should it be, though?

I want to look at typical arguments I hear used to belittle HTML and offer my own rebuttals to show how those claims are not completely correct.

My goal is not to prove that HTML is or is not a programming language, but to show that the three main arguments used for claiming it is not are flawed or incorrect, thus invalidating the conclusion from a logical point of view.

“HTML is a markup language, not a programming language”

This statement, by itself, sounds great… but it is wrong: markup languages can be programming languages. Not all of them are (most are not) but they can be. If we drew a Venn diagram of programming languages and markup languages, it would not be two separate circles, but two circles that slightly intersect:

A markup language that operates with variables, has control structures, loops, etc., would also be a programming language. They are not mutually exclusive concepts.

TeX and LaTeX are examples of markup languages that are also considered programming languages. It may not be practical to develop with them, but it is possible. And we can find examples online, like a BASIC interpreter or a Mars Rover controller (which won the Judges’ prize in the ICFP 2008 programming contest).

While some markup languages might be considered programming languages, I’m not saying that HTML is one of them. The point is that the original statement is wrong: markup languages can be programming languages. Therefore, saying that HTML is not a programming language because it is a markup language is based on a false statement, and whatever conclusion you arrive at from that premise will be categorically wrong.

“HTML doesn’t have logic”

This claim demands that we clarify what “logic” means because the definition might just surprise you.

As with Turing-completeness (which we’ll definitely get to), those who bring this argument to the table seem to misunderstand what it is exactly. I’ve asked people to tell me what they mean by “logic” and have gotten interesting answers back like:

Logic is a sensible reason or way of thinking.

That’s nice if what we’re looking for is a dictionary definition of logic. But we are talking about programming logic, not just logic as a general term. I’ve also received answers like:

Programming languages have variables, conditions, loops, etc. HTML is not a programming language because you can’t use variables or conditions. It has no logic.

This is fine (and definitely better than getting into true/false/AND/OR/etc.), but also incorrect. HTML does have variables — in the form of attributes — and there are control structures that can be used along with those variables/attributes to determine what is displayed.

But how do you control those variables? You need JavaScript!

Wrong again. There are some HTML elements that have internal control logic and don’t require JavaScript or CSS to work. And I’m not talking about things like <link> or <noscript> – which are rudimentary control structures and have been part of the standard for decades. I’m referring to elements that will respond to the user input and perform conditional actions depending on the current state of the element and the value of a variable. Take the <details>/<summary> tuple or the <dialog> element as examples: when a user clicks on them, they will close if the open attribute is present, and they will open if it is not. No JavaScript required.

So just saying alone that HTML isn’t a programming language because it lacks logic is misleading. We know that HTML is indeed capable of making decisions based on user input. HTML has logic, but it is inherently different from the logic of other languages that are designed to manipulate data. We’re going to need a stronger argument than that to prove that HTML isn’t a form of programming.

“HTML is not ‘Turing complete’”

OK, this is the one we see most often in this debate. It’s technically correct (the best kind of correct) to say HTML is not Turing complete, but it should spark a bigger debate than just using it as a case-closing statement.

I’m not going to get into the weeds on what it means to be Turing complete because there are plenty of resources on the topic. In fact, Lara Schenck summarizes it nicely in a post where she argues that CSS is Turning complete:

In the simplest terms, for a language or machine to be Turing complete, it means that it is capable of doing what a Turing machine could do: perform any calculation, a.k.a. universal computation. After all, programming was invented to do math although we do a lot more with it now, of course!

Because most modern programming languages are Turing complete, people use that as the definition of a programming language. But Turing-completeness is not that. It is a criterion to identify if a system (or its ruleset) can simulate a Turing machine. It can be used to classify programming languages; it doesn’t define them. It doesn’t even apply exclusively to programming languages. Take, for example, the game Minecraft (which meets that criterion) or the card game Magic: The Gathering (which also meets the criterion). Both are Turing complete but I doubt anyone would classify them as programming languages.

Turing-completeness is fashionable right now the same way that some in the past considered the difference between compiled vs. interpreted languages to be good criteria. Yes. We don’t have to make a big memory effort to remember when developers (mainly back-end) downplayed front-end programming (including JavaScript and PHP) as not “real programming.” You still hear it sometimes, although now faded, mumbled, and muttered.

The definition of what programming is (or is not) changes with time. I bet someone sorting through punched cards complained about how typing code in assembly was not real programming. There’s nothing universal or written in stone. There’s no actual definition.

Turing-completeness is a fair standard, I must say, but one that is biased and subjective — not in its form but in the way it is picked. Why is it that a language capable of generating a Turing Complete Machine gets riveted as a “programming language” while another capable of generating a Finite State Machine is not? It is subjective. It is an excuse like any other to differentiate between “real developers” (the ones making the claim) and those inferior to them.

To add insult to injury, it is obvious that many of the people parroting the “HTML is not Turing complete” mantra don’t even know or understand what Turing-completeness means. It is not an award or a seal of quality. It is not a badge of honor. It is just a way to categorize programming languages — to group them, not define them. A programming language could be Turing complete or not in the same way that it could be interpreted or compiled, imperative or declarative, procedural or object-oriented.

So, is HTML a programming language?

If we can debase the main arguments claiming that HTML is not a programming language, does that actually mean that HTML is a programming language? No, it doesn’t. And so, the debate will live on until the HTML standard evolves or the “current definition” of programming language changes.

But as developers, we must be wary of this question as, in many cases, it is not used to spark a serious debate but to stir controversy while hiding ulterior motives: from getting easy Internet reactions, to dangerously diminishing the contribution of a group of people to the development ecosystem.

Or, as Ashley Kolodziej beautifully sums it up in her ode to HTML:

They say you’re not a real programming language like the others, that you’re just markup, and technically speaking, I suppose that’s right. Technically speaking, JavaScript and PHP are scripting languages. I remember when it wasn’t cool to know JavaScript, when it wasn’t a “real” language too. Sometimes, I feel like these distinctions are meaningless, like we built a vocabulary to hold you (and by extension, ourselves as developers) back. You, as a markup language, have your own unique value and strengths. Knowing how to work with you best is a true expertise, one that is too often overlooked.

Independent of the stance that we take on the “HTML is/isn’t a programming language” discussion, let’s celebrate it and not deny its importance: HTML is the backbone of the Internet. It’s a beautiful language with vast documentation and extensive syntax, yet so simple that it can be learned in an afternoon, and so complex that it takes years to master. Programming language or not, what really matters is that we have HTML in the first place.

The post HTML is Not a Programming Language? appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.


, ,

Is CSS a Programming Language?

I have a real distaste for this question. It might seem like a fun question to dig into on the surface, but the way it enters public discourse rarely seems to be in good faith. There are ulterior motives at play involving respect, protective emotions, and desires to break or maintain the status quo.

If someone can somehow prove that CSS isn’t a programming language (this is such a gray area that if that was your goal, it wouldn’t be terribly hard to do) then they get to keep on feeling superior in their “real” programming skills and rationalize the fact that they are (likely) paid more than a front-of-the-front-ender specializing in CSS. This is maintaining the status quo.

The reverse can also be true. If you can prove that CSS is a programming language, perhaps you can shift your own company or the industry at large toward equal respect and pay toward front-of-the-front-end developers. This is breaking the status quo.

Let’s say we could all agree on a boolean true or false on if CSS is a programming language. What now? If true, is pay normalized among all web workers? If false, do CSS specialists deserve pay cuts? If true, does everyone start respecting each other in a way they don’t now? If false, do CSS people have to eat lunch in the boiler room? I have doubts that anything will change; hence my distaste for the discussion at all.

Whatever the facts, it’s unlikely most people are going to accept even the possibility that CSS is a programming language. I mean, programs execute, don’t they? Nobody doubts that JavaScript is a programming language, because it executes. You write code and then execute that code. Perhaps you open a terminal window and write:

> node my-program.js

Sure as eggs is eggs, that program will execute. You can make “Hello, World!” print to the terminal with console.log("Hello, World!");.

CSS can’t do that! Um, well, unless you write body::after { content: "Hello, World!"; } in style.css file and open a web page that loads that CSS file. So CSS does execute, in its own special way. It’s a domain-specific language (DSL) rather than a general-purpose language (GPL). In that browser context, the way CSS is told to run (<link>, usually) isn’t even that different from how JavaScript is told to run (<script>, usually).

If you’re looking for comparisons for CSS syntax to programming concepts, I think you’ll find them. What is a selector if not a type of if statement that runs a loop over matches? What is calc() if not a direct implementation of math? What is a group of media queries if not a switch? What is a custom property if not a place to store state? What is :checked if not boolean? Eric recently made the point that CSS is typed, and earlier, that CSS is chock full of functions.

For better or worse, having an answer to whether or not CSS is a programming language affects people. One college professor had made a point of telling students that CSS is not Turing complete, but is now re-considering that position upon learning that it is. Whatever the intention there, I think the industry is affected by what computer science professors tell computer science students year after year.

Lara Schenck has dug into the Turing-complete angle. If you’re trying to settle this, Turing completeness is a good proxy. It turns out that CSS basically is Turing complete (by settling the cellular automaton angle of Rule 110), just not entirely by itself. It involves a somewhat complex use of selectors and :checked (surprise, surprise). Lara makes an astute point:

Alone, CSS is not Turing complete. CSS plus HTML plus user input is Turing complete!

Still, say you don’t buy it. You get it and even concede, OK fine, CSS is essentially Turing complete, but it just doesn’t feel like CSS (or HTML for that matter) is a programming language to you. It’s too declarative. Too application-specific. Whatever it is, I honestly don’t blame you. What I hope is that whatever conclusion you come to, the answer doesn’t affect things that really matter1, like pay and respect.

Respect is in order, no matter what any of us come to for an answer. I don’t consider CSS a programming language, but it doesn’t mean I think it’s trivial or that my specialist co-workers are any less valuable than my Python specialist co-workers. Wouldn’t that be nice? I think there is an interesting distinction between declarative markup languages and other types of languages, but they are all code. Oh stop it, you know how thoughtful answers make me blush.

I’d like to see a lot more nuanced, respectful, and agenda-less comments like that when these discussions happen.

  1. Just like “website” vs “web app.” Whether or not you think there is a distinction, I would hope people aren’t making decisions that affect users based on what taxonomical bucket you think your thing goes in.

The post Is CSS a Programming Language? appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



CSS is a Strongly Typed Language

One of the ways you can classify a programming language is by how strongly or weakly typed it is. Here, “typed” means if variables are known at compile time. An example of this would be a scenario where an integer (1) is added to a string containing an integer ("1"):

result = 1 + "1";

The string containing an integer could have been unintentionally generated from a complicated suite of logic with lots of moving parts. It could also have been intentionally generated from a single source of truth.

Despite the connotations that the terms “weak” and “strong” imply, a strongly-typed programming language isn’t necessarily better than a weakly-typed one. There may be scenarios where flexibility is needed more than rigidity, and vice-versa. As with many aspects of programming, the answer is dependent on multiple external contexts (i.e “it depends”).

The other interesting bit is there is no formal definition of what constitutes strong or weak typing. This means that perceptions of what is considered a strongly or weakly-typed language differ from person to person, and may change over time.


JavaScript is considered a weakly-typed language, and this flexibility contributed to its early adoption on the web. However, as the web has matured and industrialized, use cases for JavaScript have become more complicated.

Extensions like TypeScript were created to help with this. Think of it as a “plugin” for JavaScript, which grafts strong typing onto the language. This helps programmers navigate complicated setups. An example of this could be a data-intensive single page application used for e-commerce.

TypeScript is currently very popular in the web development industry, and many new projects default to using TypeScript when first setting things up.

Compile time

Compile time is the moment when a programming language is converted into machine code. It is a precursor to runtime, the moment when machine code is performed by the computer.

As with many things on the web, compile time is a bit tricky. A setup that utilizes TypeScript will stitch together component pieces of JavaScript code and compile them into a single JavaScript file for the browser to read and run.

The time when component pieces compile is when they are all combined. TypeScript serves as a kind of overseer, and will yell at you if you try to break the typed conventions you have set up for yourself before combination occurs.

A tooltip that reads, “var content: any. Property ‘content’ does not exist on type ‘PropsWithChildren<Props>’. ts(2339). View Problem (Option F8). No quick fixes available. Tooltip is pointing towards an argument called “content.”
A sample TypeScript error in VS Code.

The stitched-together JavaScript file is then ingested by the browser, which has its own compile time. Browser compile time is highly variable, depending on:

  • The device the browser is on,
  • What other work the browser is doing, and
  • What other work the device’s other programs are doing.

TypeScript isn’t directly used by the browser, but its presence is felt. JavaScript is fragile. TypeScript helps with this fragility by trying to prevent errors upstream in the code editor. This lessens the chance errors occur in the JavaScript read by the browser — errors that would cause JavaScript to stop functioning on the website or web app a person is using.


CSS is a declarative, domain-specific programming language. It is also strongly typed. For the most part, values in CSS stay declared as authored. If a value is invalid the browser throws the entire property away.

Types in CSS

The list of types in CSS is thorough. They are:

Textual types
  • Globally-scoped keywords:
    • initial
    • inherit
    • unset
    • revert
  • Custom identifies, which are specifically used for things, such as providing a grid-area name
  • Strings, such as, "hello"
  • URLs, such as https://css-tricks.com/
  • Dashed idents (--), which are used to create custom properties (more on this in a bit)
Numeric types
  • Integers, which are decimal numbers 0–9
  • Real numbers, such as 3.14
  • Percentages, such as 25%
  • Dimensions, a number with a unit appended to it such as (100px or 3s)
  • Ratios, such as 16/9
  • flex, a variable length for CSS grid calculation
Quantity types
  • Lengths:
  • Angles, such as 15deg
  • Time, such as 250ms
  • Frequencies, such 16Hz
  • Resolution, such as 96dpi

Dimensions and lengths might seem similar, but dimensions can contain percentages and lengths cannot.

Color types
  • Keywords:
    • Named colors, such as papayawhip
    • transparent
    • currentColor
  • RGB colors:
    • Hexidecimal notation, such as #FF8764
    • RGB/RGBa notation, such as rgba(105, 221, 174, 0.5)
  • HSL/HSLA colors, such as hsl(287, 76%, 50%)
  • System colors, such as ButtonText
Image types
  • Image, which is a URL reference to an image file or gradient
  • color-stop-list, a list of two or more color stops, used for gradient notion
  • linear-color-stop, a color and length expression used to indicate a gradient color stop
  • linear-color-hint, a length percentage used to interpolate color
  • ending-shape, which uses a keyword of either circle or ellipse for radial gradients
2D positioning types
  • Keywords:
    • top
    • right
    • bottom
    • left
    • center
  • A percentage length, such as 25%

Programming in CSS

The bulk of programming in CSS is authoring selectors, then specifying a suite of properties and their requisite values. Collections of selectors give content a visual form, much as how collections of JavaScript logic creates features.

CSS has functions. It can perform calculation, conditional logic, algorithmic expressions, state, and mode-based behavior. It also has custom properties, which are effectively CSS variables that allow values to be updated dynamically. Heck, you can even solve fizzbuzz with CSS.

Like other programming languages, there is also a “meta” layer, with different thoughts and techniques on how to organize, manage and maintain things.

Throwing errors

Unlike other programming languages where code largely exists under the hood, CSS is highly visual. You won’t see warnings or errors in the console if you use an invalid value for a property declaration, but you will get visuals that don’t update the way you anticipated.

The reason for this is that CSS is resilient. When visuals don’t update because of a misconstructed declaration, CSS is prioritizing, ensuring content can be shown at all costs and will render every other valid declaration it possibly can. This is in keeping with the design principles of the language, the principles of the platform, and the overarching goals of the web’s mission.


Let’s demonstrate how strong typing in CSS keeps the guardrails on in three examples: one with a straightforward property/value declaration, one with calculation, and one with redefining a custom property.

Example 1: Straightforward property/value declaration

See the Pen Basic example by Eric Bailey (@ericwbailey) on CodePen.

For this example, the browser does not understand the banner’s border-style “potato” declaration. Note that the other .banner class selector property/value declarations are honored by the browser and rendered, even though border-style has a type mismatch. This is an example of how resilient CSS is.

The border-style declaration is expecting one of the following textual style types:

  • Globally-scoped keywords, or a
  • Dashed indent for a custom property.

If we update border-style to use a valid, typed value of dotted, the browser will render the border!

Example 2: Calculation

The calc() function in CSS allows us to take two arguments and an operator to return a calculated result. If one of the arguments doesn’t use a valid type, the calculation won’t work.

In this Pen, the p selector’s font-size property is expecting a value with a numeric dimension type (e.g. 1.5rem). However, the calculation function produces an invalid type value for the font-size property. This is because the second argument in the calc() function is a string ("2rem"), and not a numeric dimension type.

Because of this, the paragraph’s font size falls back to the next most applicable parent node — the font-size of 1.5rem declared on the body element.

This is a bit in the weeds, but worth pointing out: Combining two custom properties in a calc() function can cause errors. While both custom properties may be valid on their own, calc() will not accept dashed indent textual types. Think of a scenario where we might try multiplying custom properties that contain mismatched units, e.g. --big: 500px and --small: 1em.

Example 3: Redefined custom property

Like JavaScript variables, custom property values can be redefined. This flexibility allows for things like easily creating dark mode color themes.

In the :root selector of this CodePen, I have set a custom property of --color-cyan, with a value of #953FE3. Then, in the .square class, I have updated the --color-cyan custom property’s value to be top. While top is a valid, typed value, it is not a type that background-color honors.

Notice that the updated custom property is scoped to .square, and does not affect other usages, such as the right-hand border on the phrase “Don’t play to type.” And if you remove the redefined custom property from .square, you’ll see the cyan background color snap back in.

While this is a bit contrived, it serves as an example of how redefining custom properties can get away from you if you’re not careful.

This phenomenon can be found in projects with poor communication, larger CSS codebases, and situations where CSS preprocessors are used to construct custom properties at scale.


With the gift of hindsight, I think a lack of console warnings for CSS is a flaw, and has contributed to a lot of the negative perceptions about the language.

Hoping a developer will notice a potentially tiny visual change is too big an ask, and does not meet them where they are for most of their other daily tools. There are a couple of initiatives I’m aware of that try to address this.

First is stylelint, a linter made specifically to deal with CSS and CSS-like preprocessing languages. stylelint can integrate with code editors, task runners, command line tools, and GitHub actions to help keep your CSS under control. This allows it to meet developers where they already are.

A tooltip that reads, “var content: any. Property ‘content’ does not exist on type ‘PropsWithChildren<Props>’. ts(2339). View Problem (Option F8). No quick fixes available. Tooltip is pointing towards an argument called “content.”
stylelint terminal output.

Second is Firefox’s excellent suite of CSS inspection options in its Developer Tools. In particular, I would like to call attention to its ability to identify unused CSS. This is extremely helpful for identifying selectors that may have run afoul of a type mismatch.

Tooltip attached to an unused selector in the Developer panel. The tooltip reads, “vertical-align has no effect on this element since it’s not an inline or table-cell element. Try adding display: inline or display: table-cell. Learn more. Screenshot.”
Firefox Developer edition

Wrapping up

CSS has been strongly typed for as long as it has been a programming language, and as a programming language it has been around for a long time. It’s also done a lot of growing up lately. If you haven’t checked in, there are some new, amazing features available.

As strongly-typed JavaScript becomes more popular, it is my hope that it helps developers become more comfortable with the firm, yet flexible approach of CSS.

Thank you to Miriam Suzanne for her feedback.

The post CSS is a Strongly Typed Language appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.


, ,

To the brain, reading computer code is not the same as reading language

One of the things I do when teaching beginning front-end development is ask students to describe what it’s like to read HTML. I give them pretty basic markup for a long-form article, and ask them to read it twice: first in the code, then on the front end.

The #1 common response I hear? It’s like learning a new language.

Of course it is, I tell them. It’s in the name: Hypertext Markup Language. So, I advise them to start treating the materials in the course like they’re learning French, Spanish, or any other language.

Then I wake up this morning and see this MIT study that reading computer code is not the same as reading language, even though they share similarities.

In spite of those similarities, MIT neuroscientists have found that reading computer code does not activate the regions of the brain that are involved in language processing. Instead, it activates a distributed network called the multiple demand network, which is also recruited for complex cognitive tasks such as solving math problems or crossword puzzles.

Duh, you might say. But wait, reading code actually appears to activate additional parts of the multiple demand network that make the task more or a near-match to mathematical reasoning than the exact same thing.

The MIT team found that reading computer code appears to activate both the left and right sides of the multiple demand network […]. This finding goes against the hypothesis that math and coding rely on the same brain mechanisms.

So, back to my HTML reading assignment. Is it better to teach code as a language for recognizing symbols that communicate to the browser what to do, or as a math skill that’s based on solving problems?

The answer is 🤷‍♂️.

The most interesting thing about the study to me is not how to teach code, but rather how how I work with it. Chris always says a front-end developer is aware, and the fact that reading code taps on a region of the brain that’s responsible for handling multi-tasking and holding lots of information only supports that. It also explains why I personally get annoyed when I’m pulled away from my code or distracted from it—it’s like my brain has to drop all the plates it was balancing to pay attention to something else, then pick up and reassemble all the pieces before I can jump back in to what I was doing.

Direct Link to ArticlePermalink

The post To the brain, reading computer code is not the same as reading language appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.


, , , , ,