Join Us On The Dark Side

For April Fools Day this year, the engineering team at Grata decided to surprise users with a dark theme of our app. Join us on the Dark Side!
Join Us On The Dark Side

For April Fools Day this year, the engineering team at Grata decided to surprise users with a dark theme of our app, welcoming them with a message from well known dark theme enthusiast:

Grata home screen on April Fools' Day

To convert the entire application to a dark theme as quickly as possible, while still allowing users the ability to switch back to a light theme, we took advantage of a new technique for our codebase: CSS Variables.

To avoid having to individually add a dark version for every element and style in our platform, we decided to convert all existing color-related styling to reference variables instead. Doing so allows us to edit a color once and all areas in the platform where that is used would change together.

Given the inheritance rules for CSS variables, we were able to add a single class to <body> and override all existing colors with dark versions for each. And because our platform mainly uses different shades of grays, we can simply inverse the RGB values to achieve similar effects coming from the dark direction. So if we start with the value rgb(245,245,255) in the existing theme, we can calculate the distance from white for each color (so 255 - 245 = 10) and map that as a starting point from 0. Our example becomes rgb(10,10,20).

You may have noticed we didn't do that for the blue value; that is because we tend to add a bit of blue to all of our grays in the platform, and if we were to use the same logic as we do for red and green, it would change the tone of the platform to be more purple.

Comparison of dark and light themes
Alternating between Dark Mode and Light Mode

There were some cases where the grays had to be changed a bit to create a more natural look, and we ended up adding an offset value of 10 to prevent the platform from becoming too black. This allows for a more pleasant, dark-blue theme rather than a high-contrast, black theme, and also maintains the ability to add black shadows behind popups and tiles (a valuable UI aspect that is necessary to have elements stand out from each other). We also had to manually touch up a few elements that didn't stand out enough or looked odd with this mathematical inversion approach, stepping in for individually selected dark theme colors. So now, our platform looks a bit like this. We first define the raw RGB values upfront, and reference them in our color variables.

 /* brand colors */
 --grata-green: #26d9ca; /* darkened version of logo color */
 --grata-blue: #00a3d0; /* middle color in logo */
 --grata-dark-blue: #1072bd; /* dark blue in logo */
 --logo-text: #0b568f; /* text in logo */

 /* platform colors */
 --rgb-black:      0, 0, 0;
 --rgb-white:      255, 255, 255;
 --rgb-gray:       115, 115, 130;
 --rgb-gray-50:    50, 50, 60;
 ...
 --rgb-gray-253:   253, 253, 255;

 --black:          rgb(var(--rgb-black));
 --white:          rgb(var(--rgb-white));
 --gray:           rgb(var(--rgb-gray));
 --gray-50:        rgb(var(--rgb-gray-50));
 ...
 --gray-253:       rgb(var(--rgb-gray-253));
 --green:          #00C086;
 --limegreen:      #67CE1E;
 --seagreen:       #0D8BA5;
 --blue:           #08a1dd;
 --darkblue:       #3284E3;
 --orange:         #FF7F1D;
 --purple:         #574FB9;
 --magenta:        #BB62D3;
 --lilac:          #818AFE;
 --yellow:         #FFA400;
 --teal:           #13C2C2;
 --pink:           #E1528D;
 --red:            #F4342A;

Then for the dark theme, we override the raw RGB values, which are still referenced above by the color variables. By keeping the black-point offset a variable, we're able to dynamically shift the brightness of the dark theme without having to individually calculate or update each gray value.

html.dark {
 color: white;
 --logo-text:              var(--grata-dark-blue);
 --grata-dark-blue:        var(--grata-blue);
 --c-offset:       10;

 /* platform colors */
 --rgb-white:      20, 20, 30;
 --rgb-black:      calc(var(--c-offset) + 255), calc(var(--c-offset) + 255), calc(var(--c-offset) + 255);
 --rgb-gray:       calc(var(--c-offset) + 140), calc(var(--c-offset) + 140), calc(var(--c-offset) + 150);
 --rgb-gray-50:    calc(var(--c-offset) + 205), calc(var(--c-offset) + 205), calc(var(--c-offset) + 215);
 ...
 --rgb-gray-253:   calc(var(--c-offset) + 2), calc(var(--c-offset) + 2), calc(var(--c-offset) + 4);

 --box-shadow:     0 1px 6px 0 rgba(0, 0, 0, 0.56), 0 2px 32px 0 rgba(0, 0, 0, 0.66), inset 0 0 0 3px var(--gray-240);
 --tile-shadow:    0 -1px 3px rgba(0,0,0,0.55), 0 1px 2px rgba(0,0,0,0.62);
 ...
}

We'll be highlighting more of our engineering process, explorations through new technologies, challenges and more soon!


Subscribe to our newsletter

Monthly tactics from Grata’s team and operators.

Related
Articles

From market trends to career advice, Grata’s content fuels smarter decisions.

The PE Playbook: Sports Services
Market Trends
Private Equity
Corporate Development

The PE Playbook: Sports Services

Discover all of the trends that private market dealmakers need to know about the global sports services industry, from how the industry is fragmented to high-growth sectors to geographical opportunities.
How Agentic AI Is Changing M&A Workflows
AI & Automation

How Agentic AI Is Changing M&A Workflows

Agentic AI is set to transform the M&A world. Learn about how the revolutionary tech is changing each step of the dealmaking process in this article from Grata.
The 5 US Industries Most Crowded with Dealmakers and Short on Sellers
Acquisition
Buy-Side
Market Trends

The 5 US Industries Most Crowded with Dealmakers and Short on Sellers

Grata data reveals five U.S. industries crowded with dealmakers but short on willing sellers—and why early deal intelligence matters more than ever.
Virtual Data Rooms in Private Market Dealmaking: From Sourcing to Secure Diligence
Diligence
Data/Analytics
AI & Automation

Virtual Data Rooms in Private Market Dealmaking: From Sourcing to Secure Diligence

Private market dealmaking doesn't stop at discovery. When your team is ready to move from opportunity identification to secure diligence, you need a purpose-built M&A data room to help manage confidential information, buyer engagement, Q&A, and transaction workflows with confidence.
10 Industries Where High Seller Intent Is Trending Up
Consumer
Healthcare
Financial Services
Industrials
Private Equity

10 Industries Where High Seller Intent Is Trending Up

From real estate to retail to finance & insurance, see which 10 industries are seeing increases in seller intent and what's driving the changes.
From Deal Sourcing to the Datasite Diligence Data Room: Why Private Market Data Needs a Secure Execution Layer
AI & Automation

From Deal Sourcing to the Datasite Diligence Data Room: Why Private Market Data Needs a Secure Execution Layer

See how AI connects private market intelligence, deal sourcing, diligence preparation, and secure data room execution through Grata, Blueflame AI, and Datasite Diligence.
How to Build an AI-Native Deal Sourcing Engine
AI & Automation
Sourcing

How to Build an AI-Native Deal Sourcing Engine

Learn how to build an AI-native deal sourcing engine by combining tools like Claude with Grata's private market intelligence and MCP connectivity.
Blue backgound