diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b5955efea894309b2306b4687119dc8d1396c0c..39ef3c7219c9ef847c4fa20313eb995308d7d96e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ current (development)
 ### Dom
 - Feature: Add the dashed style for border and separator.
 - Feature: Add colored borders.
+- Feature: Customize with gradient color effect. Add the following decorators:
+  - `colorgrad`
+  - `bgcolorgrad`
+- Improvement: Color::Interpolate() uses gamma correction.
 
 ###
 - Breaking: Direction enum is renamed WidthOrHeight
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6f28c457b6eb19dcc5573999a5c07266e6f0b781..c52c3391cdff410f6a36d04dfef97f1b5307a868 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,6 +72,7 @@ add_library(dom
   src/ftxui/dom/gridbox.cpp
   src/ftxui/dom/hbox.cpp
   src/ftxui/dom/inverted.cpp
+  src/ftxui/dom/linear_gradient.cpp
   src/ftxui/dom/node.cpp
   src/ftxui/dom/node_decorator.cpp
   src/ftxui/dom/paragraph.cpp
diff --git a/cmake/ftxui_test.cmake b/cmake/ftxui_test.cmake
index 996e5c38fcd09df3368c73bcd14ab71c51b0d3fa..456fcb8f834413f5dd0f81659741c37a2c8fdba3 100644
--- a/cmake/ftxui_test.cmake
+++ b/cmake/ftxui_test.cmake
@@ -37,6 +37,7 @@ add_executable(ftxui-tests
   src/ftxui/dom/gauge_test.cpp
   src/ftxui/dom/gridbox_test.cpp
   src/ftxui/dom/hbox_test.cpp
+  src/ftxui/dom/linear_gradient_test.cpp
   src/ftxui/dom/scroll_indicator_test.cpp
   src/ftxui/dom/separator_test.cpp
   src/ftxui/dom/spinner_test.cpp
diff --git a/doc/mainpage.md b/doc/mainpage.md
index 40b9103ab623775501f1cf82b520540b340c79c1..6ac8572873ffa07e8d993a3602c5a70016a3ec07 100644
--- a/doc/mainpage.md
+++ b/doc/mainpage.md
@@ -442,6 +442,36 @@ ftxui::Color::HSV(uint8_t hue, uint8_t saturation, uint8_t value);
 <script id="asciicast-xwzzghmqcqzIuyLwCpQFEqbEu" src="https://asciinema.org/a/xwzzghmqcqzIuyLwCpQFEqbEu.js" async></script>
 @endhtmlonly
 
+## LinearGradient #{#dom-linear-gradient}
+
+FTXUI supports linear gradient. Either on the foreground or the background.
+
+```cpp
+Decorator color(const LinearGradient&);
+Decorator bgcolor(const LinearGradient&);
+```
+
+A `ftxui::LinearGradient` is defined by an angle in degree, and a list of color
+stops.
+```cpp
+auto gradient = LinearGradient()
+  .Angle(45)
+  .AddStop(0.0, Color::Red)
+  .AddStop(0.5, Color::Green)
+  .AddStop(1.0, Color::Blue);
+```
+
+You can also use simplified constructors:
+```cpp
+LinearGradient(Color::Red, Color::Blue);
+```
+```cpp
+LinearGradient(45, Color::Red, Color::Blue);
+```
+
+See [demo](https://arthursonzogni.github.io/FTXUI/examples/?file=component/linear_gradient_gallery).
+
+
 ## Style {#dom-style}
 In addition to colored text and colored backgrounds. Many terminals support text
 effects such as: `bold`, `dim`, `underlined`, `inverted`, `blink`.
@@ -456,6 +486,8 @@ Element strikethrough(Element);
 Element blink(Element);
 Decorator color(Color);
 Decorator bgcolor(Color);
+Decorator colorgrad(LinearGradient);
+Decorator bgcolorgrad(LinearGradient);
 ```
 
 [Example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2style_gallery_8cpp-example.html)
@@ -560,8 +592,7 @@ Simple [example](https://github.com/ArthurSonzogni/FTXUI/blob/master/examples/do
 
 Complex [example](https://github.com/ArthurSonzogni/FTXUI/blob/master/examples/component/canvas_animated.cpp):
   
-![ezgif com-gif-maker (3)](https://user-images.githubusercontent.com/4759106/147250538-783a8246-98e0-4a25-b032-3bd3710549d1.gif)  
-
+![ezgif com-gif-maker (3)](https://user-images.githubusercontent.com/4759106/147250538-783a8246-98e0-4a25-b032-3bd3710549d1.gif)
 # component {#module-component}
 
 The `ftxui::component` module defines the logic that produces interactive
diff --git a/examples/component/CMakeLists.txt b/examples/component/CMakeLists.txt
index 5b618d2bc02378b881a31569a9ca7c2fb19ffe1a..c08069092bfc16bb809731c665be70cbc5dcf757 100644
--- a/examples/component/CMakeLists.txt
+++ b/examples/component/CMakeLists.txt
@@ -17,6 +17,7 @@ example(focus_cursor)
 example(gallery)
 example(homescreen)
 example(input)
+example(linear_gradient_gallery)
 example(maybe)
 example(menu)
 example(menu2)
diff --git a/examples/component/linear_gradient_gallery.cpp b/examples/component/linear_gradient_gallery.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e0368c81ed7ef99ecfac556b01e5d802e87a80b2
--- /dev/null
+++ b/examples/component/linear_gradient_gallery.cpp
@@ -0,0 +1,56 @@
+#include <ftxui/component/component_base.hpp>  // for ComponentBase, Component
+#include <ftxui/dom/elements.hpp>  // for operator|, Element, flex, bgcolor, text, vbox, center
+#include <ftxui/dom/linear_gradient.hpp>  // for LinearGradient
+#include <ftxui/screen/color.hpp>         // for Color, Color::Blue, Color::Red
+#include <memory>                         // for __shared_ptr_access, shared_ptr
+#include <string>  // for allocator, operator+, char_traits, string, to_string
+
+#include "ftxui/component/captured_mouse.hpp"  // for ftxui
+#include "ftxui/component/component.hpp"       // for Slider, Renderer, Vertical
+#include "ftxui/component/screen_interactive.hpp"  // for ScreenInteractive
+
+int main(int argc, const char* argv[]) {
+  using namespace ftxui;
+  auto screen = ScreenInteractive::Fullscreen();
+
+  int angle = 180.f;
+  float start = 0.f;
+  float end = 1.f;
+
+  std::string slider_angle_text;
+  std::string slider_start_text;
+  std::string slider_end_text;
+
+  auto slider_angle = Slider(&slider_angle_text, &angle, 0, 360);
+  auto slider_start = Slider(&slider_start_text, &start, 0.f, 1.f);
+  auto slider_end = Slider(&slider_end_text, &end, 0.f, 1.f);
+
+  auto layout = Container::Vertical({
+      slider_angle,
+      slider_start,
+      slider_end,
+  });
+
+  auto renderer = Renderer(layout, [&] {
+    slider_angle_text = "angle = " + std::to_string(angle) + "°";
+    slider_start_text = "start = " + std::to_string(int(start * 100)) + "%";
+    slider_end_text = "end   = " + std::to_string(int(end * 100)) + "%";
+
+    auto background = text("Gradient") | center |
+                      bgcolor(LinearGradient()
+                                  .Angle(angle)
+                                  .Stop(Color::Blue, start)
+                                  .Stop(Color::Red, end));
+    return vbox({
+               background | flex,
+               layout->Render(),
+           }) |
+           flex;
+  });
+
+  screen.Loop(renderer);
+}
+
+// Copyright 2023 Arthur Sonzogni. All rights reserved.
+// Use of this source code is governed by the MIT license that can be found in
+// the LICENSE file.
diff --git a/examples/dom/CMakeLists.txt b/examples/dom/CMakeLists.txt
index 79235364297cbf2d11d48eafe7d2a0e37e9f5cab..ad3285e9ea9ef01c0aeaef7089b6ab75b61b2265 100644
--- a/examples/dom/CMakeLists.txt
+++ b/examples/dom/CMakeLists.txt
@@ -3,18 +3,19 @@ set(DIRECTORY_LIB dom)
 example(border)
 example(border_colored)
 example(border_style)
+example(canvas)
 example(color_gallery)
 example(color_info_palette256)
 example(color_truecolor_HSV)
 example(color_truecolor_RGB)
 example(dbox)
-example(canvas)
 example(gauge)
 example(gauge_direction)
 example(graph)
 example(gridbox)
 example(hflow)
 example(html_like)
+example(linear_gradient)
 example(package_manager)
 example(paragraph)
 example(separator)
diff --git a/examples/dom/linear_gradient.cpp b/examples/dom/linear_gradient.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..affc370a726b36bc9c629867d77dd681cd61c5fa
--- /dev/null
+++ b/examples/dom/linear_gradient.cpp
@@ -0,0 +1,26 @@
+#include <ftxui/dom/elements.hpp>  // for bgcolor, operator|, operator|=, text, center, Element
+#include <ftxui/dom/linear_gradient.hpp>  // for LinearGradient::Stop, LinearGradient
+#include <ftxui/screen/screen.hpp>        // for Full, Screen
+#include <memory>                         // for allocator, shared_ptr
+
+#include "ftxui/dom/node.hpp"  // for Render
+#include "ftxui/screen/color.hpp"  // for Color, Color::DeepPink1, Color::DeepSkyBlue1, Color::Yellow, ftxui
+
+int main(int argc, const char* argv[]) {
+  using namespace ftxui;
+  auto document = text("gradient") | center;
+
+  document |= bgcolor(LinearGradient()
+                          .Angle(45)
+                          .Stop(Color::DeepPink1)
+                          .Stop(Color::DeepSkyBlue1));
+  auto screen = Screen::Create(Dimension::Full(), Dimension::Full());
+  Render(screen, document);
+  screen.Print();
+
+  return 0;
+}
+
+// Copyright 2023 Arthur Sonzogni. All rights reserved.
+// Use of this source code is governed by the MIT license that can be found in
+// the LICENSE file.
diff --git a/examples/dom/style_color.cpp b/examples/dom/style_color.cpp
index 6f42bd1b77866a612bd63f82e5f13348b9cbee3a..de4a293c7bb7b35ccf2d2fedd64dcd72c5d631cd 100644
--- a/examples/dom/style_color.cpp
+++ b/examples/dom/style_color.cpp
@@ -1,59 +1,60 @@
-#include <ftxui/screen/screen.hpp>  // for Full, Screen
-#include <memory>                   // for allocator
+#include <ftxui/dom/linear_gradient.hpp>  // for LinearGradient
+#include <ftxui/screen/screen.hpp>        // for Full, Screen
+#include <memory>                         // for allocator
 
-#include "ftxui/dom/elements.hpp"  // for text, bgcolor, color, vbox, Fit, filler, hbox
+#include "ftxui/dom/elements.hpp"  // for text, bgcolor, color, vbox, filler, Fit, hbox
 #include "ftxui/dom/node.hpp"      // for Render
-#include "ftxui/screen/box.hpp"    // for ftxui
-#include "ftxui/screen/color.hpp"  // for Color, Color::Black, Color::Blue, Color::BlueLight, Color::Cyan, Color::CyanLight, Color::Default, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::RedLight, Color::White, Color::Yellow, Color::YellowLight
+#include "ftxui/screen/color.hpp"  // for Color, operator""_rgb, Color::Black, Color::Blue, Color::BlueLight, Color::Cyan, Color::CyanLight, Color::DeepSkyBlue4, Color::Default, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::RedLight, Color::SkyBlue1, Color::White, Color::Yellow, Color::YellowLight, ftxui
 
 int main(int argc, const char* argv[]) {
   using namespace ftxui;
-  // clang-format off
-  auto document =
-    hbox(
-      vbox(
-        color(Color::Default, text("Default")),
-        color(Color::Black, text("Black")),
-        color(Color::GrayDark, text("GrayDark")),
-        color(Color::GrayLight, text("GrayLight")),
-        color(Color::White, text("White")),
-        color(Color::Blue, text("Blue")),
-        color(Color::BlueLight, text("BlueLight")),
-        color(Color::Cyan, text("Cyan")),
-        color(Color::CyanLight, text("CyanLight")),
-        color(Color::Green, text("Green")),
-        color(Color::GreenLight, text("GreenLight")),
-        color(Color::Magenta, text("Magenta")),
-        color(Color::MagentaLight, text("MagentaLight")),
-        color(Color::Red, text("Red")),
-        color(Color::RedLight, text("RedLight")),
-        color(Color::Yellow, text("Yellow")),
-        color(Color::YellowLight, text("YellowLight")),
-        color(0x66ff66_rgb, text("Phosphor"))
-      ),
-      vbox(
-        bgcolor(Color::Default, text("Default")),
-        bgcolor(Color::Black, text("Black")),
-        bgcolor(Color::GrayDark, text("GrayDark")),
-        bgcolor(Color::GrayLight, text("GrayLight")),
-        bgcolor(Color::White, text("White")),
-        bgcolor(Color::Blue, text("Blue")),
-        bgcolor(Color::BlueLight, text("BlueLight")),
-        bgcolor(Color::Cyan, text("Cyan")),
-        bgcolor(Color::CyanLight, text("CyanLight")),
-        bgcolor(Color::Green, text("Green")),
-        bgcolor(Color::GreenLight, text("GreenLight")),
-        bgcolor(Color::Magenta, text("Magenta")),
-        bgcolor(Color::MagentaLight, text("MagentaLight")),
-        bgcolor(Color::Red, text("Red")),
-        bgcolor(Color::RedLight, text("RedLight")),
-        bgcolor(Color::Yellow, text("Yellow")),
-        bgcolor(Color::YellowLight, text("YellowLight")),
-        bgcolor(0x66ff66_rgb, text("Phosphor"))
-      ),
-      filler()
-    );
-  // clang-format on
+  auto document = hbox({
+      vbox({
+          color(Color::Default, text("Default")),
+          color(Color::Black, text("Black")),
+          color(Color::GrayDark, text("GrayDark")),
+          color(Color::GrayLight, text("GrayLight")),
+          color(Color::White, text("White")),
+          color(Color::Blue, text("Blue")),
+          color(Color::BlueLight, text("BlueLight")),
+          color(Color::Cyan, text("Cyan")),
+          color(Color::CyanLight, text("CyanLight")),
+          color(Color::Green, text("Green")),
+          color(Color::GreenLight, text("GreenLight")),
+          color(Color::Magenta, text("Magenta")),
+          color(Color::MagentaLight, text("MagentaLight")),
+          color(Color::Red, text("Red")),
+          color(Color::RedLight, text("RedLight")),
+          color(Color::Yellow, text("Yellow")),
+          color(Color::YellowLight, text("YellowLight")),
+          color(0x66ff66_rgb, text("Phosphor")),
+          color(LinearGradient(Color::SkyBlue1, Color::DeepSkyBlue4),
+                text("Skyblue to DeepSkyBlue")),
+      }),
+      vbox({
+          bgcolor(Color::Default, text("Default")),
+          bgcolor(Color::Black, text("Black")),
+          bgcolor(Color::GrayDark, text("GrayDark")),
+          bgcolor(Color::GrayLight, text("GrayLight")),
+          bgcolor(Color::White, text("White")),
+          bgcolor(Color::Blue, text("Blue")),
+          bgcolor(Color::BlueLight, text("BlueLight")),
+          bgcolor(Color::Cyan, text("Cyan")),
+          bgcolor(Color::CyanLight, text("CyanLight")),
+          bgcolor(Color::Green, text("Green")),
+          bgcolor(Color::GreenLight, text("GreenLight")),
+          bgcolor(Color::Magenta, text("Magenta")),
+          bgcolor(Color::MagentaLight, text("MagentaLight")),
+          bgcolor(Color::Red, text("Red")),
+          bgcolor(Color::RedLight, text("RedLight")),
+          bgcolor(Color::Yellow, text("Yellow")),
+          bgcolor(Color::YellowLight, text("YellowLight")),
+          bgcolor(0x66ff66_rgb, text("Phosphor")),
+          bgcolor(LinearGradient(Color::SkyBlue1, Color::DeepSkyBlue4),
+                  text("Skyblue to DeepSkyBlue")),
+      }),
+      filler(),
+  });
 
   auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
   Render(screen, document);
diff --git a/include/ftxui/dom/elements.hpp b/include/ftxui/dom/elements.hpp
index 2b615a2cf4bbd43d0a274c2130f33cb6bfe9d930..b414c76314c4046e964fd2a977b3ccf42a641500 100644
--- a/include/ftxui/dom/elements.hpp
+++ b/include/ftxui/dom/elements.hpp
@@ -7,6 +7,7 @@
 #include "ftxui/dom/canvas.hpp"
 #include "ftxui/dom/direction.hpp"
 #include "ftxui/dom/flexbox_config.hpp"
+#include "ftxui/dom/linear_gradient.hpp"
 #include "ftxui/dom/node.hpp"
 #include "ftxui/screen/box.hpp"
 #include "ftxui/screen/color.hpp"
@@ -99,8 +100,12 @@ Element blink(Element);
 Element strikethrough(Element);
 Decorator color(Color);
 Decorator bgcolor(Color);
+Decorator color(const LinearGradient&);
+Decorator bgcolor(const LinearGradient&);
 Element color(Color, Element);
 Element bgcolor(Color, Element);
+Element color(const LinearGradient&, Element);
+Element bgcolor(const LinearGradient&, Element);
 Decorator focusPosition(int x, int y);
 Decorator focusPositionRelative(float x, float y);
 Element automerge(Element child);
diff --git a/include/ftxui/dom/linear_gradient.hpp b/include/ftxui/dom/linear_gradient.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3c6b529f7c61ef68372b711251f2b7a8fb3a492c
--- /dev/null
+++ b/include/ftxui/dom/linear_gradient.hpp
@@ -0,0 +1,52 @@
+#ifndef FTXUI_DOM_LINEAR_GRADIENT_HPP
+#define FTXUI_DOM_LINEAR_GRADIENT_HPP
+
+#include <optional>
+#include <vector>
+
+#include "ftxui/screen/color.hpp"  // for Colors
+
+namespace ftxui {
+
+/// @brief A class representing the settings for linear-gradient color effect.
+///
+/// Example:
+/// ```cpp
+/// LinearGradient()
+///    .Angle(45)
+///    .Stop(Color::Red, 0.0)
+///    .Stop(Color::Green, 0.5)
+///    .Stop(Color::Blue, 1.0);
+/// ```
+///
+/// There are also shorthand constructors:
+/// ```cpp
+/// LinearGradient(Color::Red, Color::Blue);
+/// LinearGradient(45, Color::Red, Color::Blue);
+/// ```
+struct LinearGradient {
+  float angle = 0.f;
+  struct Stop {
+    Color color = Color::Default;
+    std::optional<float> position;
+  };
+  std::vector<Stop> stops;
+
+  // Simple constructor
+  LinearGradient();
+  LinearGradient(Color begin, Color end);
+  LinearGradient(float angle, Color begin, Color end);
+
+  // Modifier using the builder pattern.
+  LinearGradient& Angle(float angle);
+  LinearGradient& Stop(Color color, float position);
+  LinearGradient& Stop(Color color);
+};
+
+}  // namespace ftxui
+
+#endif  // FTXUI_DOM_LINEAR_GRADIENT_HPP
+
+// Copyright 2023 Arthur Sonzogni. All rights reserved.
+// Use of this source code is governed by the MIT license that can be found in
+// the LICENSE file.
diff --git a/include/ftxui/screen/color.hpp b/include/ftxui/screen/color.hpp
index d7d789a24464d1a4b592e2a26984ec840aa993b7..6adf1b3c8df5ea6e825edae3b668c5c22a8bf2f7 100644
--- a/include/ftxui/screen/color.hpp
+++ b/include/ftxui/screen/color.hpp
@@ -2,7 +2,8 @@
 #define FTXUI_SCREEN_COLOR_HPP
 
 #include <cstdint>  // for uint8_t
-#include <string>   // for wstring
+#include <string>   // for string
+#include <vector>   // for vector
 
 #ifdef RGB
 // Workaround for wingdi.h (via Windows.h) defining macros that break things.
diff --git a/src/ftxui/component/button_test.cpp b/src/ftxui/component/button_test.cpp
index 8f7add68bd72ad7bf438753a0f4e0f8489773f2b..44c44aa8e7f6b50a116fb9f75f10d4defac47bc9 100644
--- a/src/ftxui/component/button_test.cpp
+++ b/src/ftxui/component/button_test.cpp
@@ -124,10 +124,10 @@ TEST(ButtonTest, Animation) {
     Screen screen(12, 3);
     Render(screen, container->Render());
     EXPECT_EQ(screen.ToString(),
-              "\x1B[1m\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m      \x1B[22m     "
-              " \x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;192;192;192m\x1B[48;2;0;0;"
+              "\x1B[1m\x1B[38;2;191;191;191m\x1B[48;2;0;0;0m      \x1B[22m     "
+              " \x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;191;191;191m\x1B[48;2;0;0;"
               "0m btn1 \x1B[22m btn2 "
-              "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;192;192;192m\x1B[48;2;0;0;"
+              "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;191;191;191m\x1B[48;2;0;0;"
               "0m      \x1B[22m      \x1B[39m\x1B[49m");
   }
   selected = 1;
@@ -135,10 +135,10 @@ TEST(ButtonTest, Animation) {
     Screen screen(12, 3);
     Render(screen, container->Render());
     EXPECT_EQ(screen.ToString(),
-              "\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m      \x1B[1m      "
-              "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;192;192;192m\x1B[48;2;0;0;"
+              "\x1B[38;2;191;191;191m\x1B[48;2;0;0;0m      \x1B[1m      "
+              "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;191;191;191m\x1B[48;2;0;0;"
               "0m btn1 \x1B[1m btn2 "
-              "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;192;192;192m\x1B[48;2;0;0;"
+              "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;191;191;191m\x1B[48;2;0;0;"
               "0m      \x1B[1m      \x1B[22m\x1B[39m\x1B[49m");
   }
   animation::Params params(2s);
@@ -148,12 +148,12 @@ TEST(ButtonTest, Animation) {
     Render(screen, container->Render());
     EXPECT_EQ(
         screen.ToString(),
-        "\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m      "
-        "\x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m      "
-        "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m "
-        "btn1 \x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m btn2 "
-        "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m    "
-        "  \x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m      "
+        "\x1B[38;2;191;191;191m\x1B[48;2;0;0;0m      "
+        "\x1B[1m\x1B[38;2;254;254;254m\x1B[48;2;127;127;127m      "
+        "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;191;191;191m\x1B[48;2;0;0;0m "
+        "btn1 \x1B[1m\x1B[38;2;254;254;254m\x1B[48;2;127;127;127m btn2 "
+        "\x1B[22m\x1B[39m\x1B[49m\r\n\x1B[38;2;191;191;191m\x1B[48;2;0;0;0m    "
+        "  \x1B[1m\x1B[38;2;254;254;254m\x1B[48;2;127;127;127m      "
         "\x1B[22m\x1B[39m\x1B[49m");
   }
   EXPECT_EQ(selected, 1);
@@ -164,12 +164,12 @@ TEST(ButtonTest, Animation) {
     Render(screen, container->Render());
     EXPECT_EQ(
         screen.ToString(),
-        "\x1B[1m\x1B[38;2;223;223;223m\x1B[48;2;64;64;64m      "
-        "\x1B[22m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m      "
-        "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;223;223;223m\x1B[48;2;64;64;64m "
-        "btn1 \x1B[22m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m btn2 "
-        "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;223;223;223m\x1B[48;2;64;64;64m  "
-        "    \x1B[22m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m      "
+        "\x1B[1m\x1B[38;2;226;226;226m\x1B[48;2;93;93;93m      "
+        "\x1B[22m\x1B[38;2;254;254;254m\x1B[48;2;127;127;127m      "
+        "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;226;226;226m\x1B[48;2;93;93;93m "
+        "btn1 \x1B[22m\x1B[38;2;254;254;254m\x1B[48;2;127;127;127m btn2 "
+        "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;226;226;226m\x1B[48;2;93;93;93m  "
+        "    \x1B[22m\x1B[38;2;254;254;254m\x1B[48;2;127;127;127m      "
         "\x1B[39m\x1B[49m");
   }
   container->OnAnimation(params);
@@ -178,12 +178,12 @@ TEST(ButtonTest, Animation) {
     Render(screen, container->Render());
     EXPECT_EQ(
         screen.ToString(),
-        "\x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;128m      "
-        "\x1B[22m\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m      "
-        "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;"
-        "128m btn1 \x1B[22m\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m btn2 "
-        "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;255;255;255m\x1B[48;2;128;128;"
-        "128m      \x1B[22m\x1B[38;2;192;192;192m\x1B[48;2;0;0;0m      "
+        "\x1B[1m\x1B[38;2;254;254;254m\x1B[48;2;127;127;127m      "
+        "\x1B[22m\x1B[38;2;191;191;191m\x1B[48;2;0;0;0m      "
+        "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;254;254;254m\x1B[48;2;127;127;"
+        "127m btn1 \x1B[22m\x1B[38;2;191;191;191m\x1B[48;2;0;0;0m btn2 "
+        "\x1B[39m\x1B[49m\r\n\x1B[1m\x1B[38;2;254;254;254m\x1B[48;2;127;127;"
+        "127m      \x1B[22m\x1B[38;2;191;191;191m\x1B[48;2;0;0;0m      "
         "\x1B[39m\x1B[49m");
   }
 }
diff --git a/src/ftxui/dom/border.cpp b/src/ftxui/dom/border.cpp
index a90554b010d169a4fd52b15fa7a01bdb5ecdca87..6b2a63b605dc1ada64bebdf9c9fdf883eb06a7ca 100644
--- a/src/ftxui/dom/border.cpp
+++ b/src/ftxui/dom/border.cpp
@@ -1,12 +1,13 @@
-#include <algorithm>  // for max
-#include <array>      // for array
-#include <memory>     // for allocator, make_shared, __shared_ptr_access
-#include <optional>
-#include <string>   // for basic_string, string
-#include <utility>  // for move
-#include <vector>   // for __alloc_traits<>::value_type
-
-#include "ftxui/dom/elements.hpp"  // for unpack, Element, Decorator, BorderStyle, ROUNDED, Elements, DOUBLE, EMPTY, HEAVY, LIGHT, border, borderDouble, borderEmpty, borderHeavy, borderLight, borderRounded, borderStyled, borderWith, window
+#include <algorithm>               // for max
+#include <array>                   // for array
+#include <ftxui/screen/color.hpp>  // for Color
+#include <memory>    // for allocator, make_shared, __shared_ptr_access
+#include <optional>  // for optional, nullopt
+#include <string>    // for basic_string, string
+#include <utility>   // for move
+#include <vector>    // for __alloc_traits<>::value_type
+
+#include "ftxui/dom/elements.hpp"  // for unpack, Element, Decorator, BorderStyle, ROUNDED, borderStyled, Elements, DASHED, DOUBLE, EMPTY, HEAVY, LIGHT, border, borderDashed, borderDouble, borderEmpty, borderHeavy, borderLight, borderRounded, borderWith, window
 #include "ftxui/dom/node.hpp"      // for Node, Elements
 #include "ftxui/dom/requirement.hpp"  // for Requirement
 #include "ftxui/screen/box.hpp"       // for Box
diff --git a/src/ftxui/dom/color_test.cpp b/src/ftxui/dom/color_test.cpp
index 0ff72c35623ec33ab00e82ca291b23a94cfa7872..3ff2d1891858cd3e935e91ac621a23b869a71571 100644
--- a/src/ftxui/dom/color_test.cpp
+++ b/src/ftxui/dom/color_test.cpp
@@ -1,9 +1,9 @@
-#include <gtest/gtest.h>
+#include <gtest/gtest.h>  // for Test, EXPECT_EQ, Message, TestPartResult, TestInfo (ptr only), TEST
 #include <string>  // for allocator
 
 #include "ftxui/dom/elements.hpp"  // for operator|, text, bgcolor, color, Element
 #include "ftxui/dom/node.hpp"      // for Render
-#include "ftxui/screen/color.hpp"   // for Color, Color::Red
+#include "ftxui/screen/color.hpp"   // for Color, Color::Red, Color::RedLight
 #include "ftxui/screen/screen.hpp"  // for Screen, Pixel
 
 namespace ftxui {
diff --git a/src/ftxui/dom/linear_gradient.cpp b/src/ftxui/dom/linear_gradient.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..39046a33862089f71d9ed60f6da057c5ff51e074
--- /dev/null
+++ b/src/ftxui/dom/linear_gradient.cpp
@@ -0,0 +1,293 @@
+#include <stddef.h>                       // for size_t
+#include <algorithm>                      // for max, min, sort, copy
+#include <cmath>                          // for fmod, cos, sin
+#include <ftxui/dom/linear_gradient.hpp>  // for LinearGradient::Stop, LinearGradient
+#include <memory>    // for allocator_traits<>::value_type, make_shared
+#include <optional>  // for optional, operator!=, operator<
+#include <utility>   // for move
+#include <vector>    // for vector
+
+#include "ftxui/dom/elements.hpp"  // for Element, Decorator, bgcolor, color
+#include "ftxui/dom/node_decorator.hpp"  // for NodeDecorator
+#include "ftxui/screen/box.hpp"          // for Box
+#include "ftxui/screen/color.hpp"   // for Color, Color::Default, Color::Blue
+#include "ftxui/screen/screen.hpp"  // for Pixel, Screen
+
+namespace ftxui {
+namespace {
+
+struct LinearGradientNormalized {
+  float angle = 0.f;
+  std::vector<Color> colors;
+  std::vector<float> positions;  // Sorted.
+};
+
+// Convert a LinearGradient to a normalized version.
+LinearGradientNormalized Normalize(LinearGradient gradient) {
+  // Handle gradient of size 0.
+  if (gradient.stops.size() == 0) {
+    return LinearGradientNormalized{
+        0.f, {Color::Default, Color::Default}, {0.f, 1.f}};
+  }
+
+  // Fill in the two extent, if not provided.
+  if (!gradient.stops.front().position) {
+    gradient.stops.front().position = 0;
+  }
+  if (!gradient.stops.back().position) {
+    gradient.stops.back().position = 1.f;
+  }
+
+  // Fill in the blank, by interpolating positions.
+  size_t last_checkpoint = 0;
+  for (size_t i = 1; i < gradient.stops.size(); ++i) {
+    if (!gradient.stops[i].position) {
+      continue;
+    }
+
+    if (i - last_checkpoint >= 2) {
+      const float min = gradient.stops[i].position.value();
+      const float max = gradient.stops[last_checkpoint].position.value();
+      for (size_t j = last_checkpoint + 1; j < i; ++j) {
+        gradient.stops[j].position =
+            min + (max - min) * (j - last_checkpoint) / (i - last_checkpoint);
+      }
+    }
+
+    last_checkpoint = i;
+  }
+
+  // Sort the stops by position.
+  std::sort(
+      gradient.stops.begin(), gradient.stops.end(),
+      [](const auto& a, const auto& b) { return a.position < b.position; });
+
+  // If we don't being with zero, add a stop at zero.
+  if (gradient.stops.front().position != 0) {
+    gradient.stops.insert(gradient.stops.begin(),
+                          {gradient.stops.front().color, 0.f});
+  }
+  // If we don't end with one, add a stop at one.
+  if (gradient.stops.back().position != 1) {
+    gradient.stops.push_back({gradient.stops.back().color, 1.f});
+  }
+
+  // Normalize the angle.
+  LinearGradientNormalized normalized;
+  normalized.angle = std::fmod(std::fmod(gradient.angle, 360.f) + 360.f, 360.f);
+  for (auto& stop : gradient.stops) {
+    normalized.colors.push_back(stop.color);
+    normalized.positions.push_back(stop.position.value());
+  }
+  return normalized;
+}
+
+Color Interpolate(const LinearGradientNormalized& gradient, float t) {
+  // Find the right color in the gradient's stops.
+  size_t i = 1;
+  while (true) {
+    if (i > gradient.positions.size()) {
+      return Color::Interpolate(0.5f, gradient.colors.back(),
+                                gradient.colors.back());
+    }
+    if (t <= gradient.positions[i]) {
+      break;
+    }
+    ++i;
+  }
+
+  const float t0 = gradient.positions[i - 1];
+  const float t1 = gradient.positions[i - 0];
+  const float tt = (t - t0) / (t1 - t0);
+
+  const Color& c0 = gradient.colors[i - 1];
+  const Color& c1 = gradient.colors[i - 0];
+  const Color& cc = Color::Interpolate(tt, c0, c1);
+
+  return cc;
+}
+
+class LinearGradientColor : public NodeDecorator {
+ public:
+  explicit LinearGradientColor(Element child,
+                               const LinearGradient& gradient,
+                               bool background_color)
+      : NodeDecorator(std::move(child)),
+        gradient_(Normalize(gradient)),
+        background_color_{background_color} {}
+
+ private:
+  void Render(Screen& screen) override {
+    const float degtorad = 0.01745329251f;
+    const float dx = std::cos(gradient_.angle * degtorad);
+    const float dy = std::sin(gradient_.angle * degtorad);
+
+    // Project every corner to get the extent of the gradient.
+    const float p1 = box_.x_min * dx + box_.y_min * dy;
+    const float p2 = box_.x_min * dx + box_.y_max * dy;
+    const float p3 = box_.x_max * dx + box_.y_min * dy;
+    const float p4 = box_.x_max * dx + box_.y_max * dy;
+    const float min = std::min({p1, p2, p3, p4});
+    const float max = std::max({p1, p2, p3, p4});
+
+    // Renormalize the projection to [0, 1] using the extent and projective
+    // geometry.
+    const float dX = dx / (max - min);
+    const float dY = dy / (max - min);
+    const float dZ = -min / (max - min);
+
+    // Project every pixel to get the color.
+    if (background_color_) {
+      for (int y = box_.y_min; y <= box_.y_max; ++y) {
+        for (int x = box_.x_min; x <= box_.x_max; ++x) {
+          const float t = x * dX + y * dY + dZ;
+          screen.PixelAt(x, y).background_color = Interpolate(gradient_, t);
+        }
+      }
+    } else {
+      for (int y = box_.y_min; y <= box_.y_max; ++y) {
+        for (int x = box_.x_min; x <= box_.x_max; ++x) {
+          const float t = x * dX + y * dY + dZ;
+          screen.PixelAt(x, y).foreground_color = Interpolate(gradient_, t);
+        }
+      }
+    }
+
+    NodeDecorator::Render(screen);
+  }
+
+  LinearGradientNormalized gradient_;
+  bool background_color_;
+};
+
+}  // namespace
+
+/// @brief Build the "empty" gradient. This is often followed by calls to
+/// LinearGradient::Angle() and LinearGradient::Stop().
+/// Example:
+/// ```cpp
+///  auto gradient =
+///   LinearGradient()
+///    .Angle(45)
+///    .Stop(Color::Red, 0.0)
+///    .Stop(Color::Green, 0.5)
+///    .Stop(Color::Blue, 1.0);;
+/// ```
+/// @ingroup dom
+LinearGradient::LinearGradient() = default;
+
+/// @brief Build a gradient with two colors.
+/// @param begin The color at the beginning of the gradient.
+/// @param end The color at the end of the gradient.
+/// @ingroup dom
+LinearGradient::LinearGradient(Color begin, Color end) {
+  stops.push_back({begin, {}});
+  stops.push_back({end, {}});
+}
+
+/// @brief Build a gradient with two colors and an angle.
+/// @param a The angle of the gradient.
+/// @param begin The color at the beginning of the gradient.
+/// @param end The color at the end of the gradient.
+/// @ingroup dom
+LinearGradient::LinearGradient(float a, Color begin, Color end) {
+  angle = a;
+  stops.push_back({begin, {}});
+  stops.push_back({end, {}});
+}
+
+/// @brief Set the angle of the gradient.
+/// @param a The angle of the gradient.
+/// @return The gradient.
+/// @ingroup dom
+LinearGradient& LinearGradient::Angle(float a) {
+  angle = a;
+  return *this;
+}
+
+/// @brief Add a color stop to the gradient.
+/// @param c The color of the stop.
+/// @param p The position of the stop.
+/// @return The gradient.
+LinearGradient& LinearGradient::Stop(Color c, float p) {
+  stops.push_back({c, p});
+  return *this;
+}
+
+/// @brief Add a color stop to the gradient.
+/// @param c The color of the stop.
+/// @return The gradient.
+/// @ingroup dom
+/// @note The position of the stop is interpolated from nearby stops.
+LinearGradient& LinearGradient::Stop(Color c) {
+  stops.push_back({c, {}});
+  return *this;
+}
+
+/// @brief Set the foreground color of an element with linear-gradient effect.
+/// @param gradient The gradient effect to be applied on the output element.
+/// @param child The input element.
+/// @return The output element colored.
+/// @ingroup dom
+///
+/// ### Example
+///
+/// ```cpp
+/// color(LinearGradient{0, {Color::Red, Color::Blue}}, text("Hello"))
+/// ```
+Element color(const LinearGradient& gradient, Element child) {
+  return std::make_shared<LinearGradientColor>(std::move(child), gradient,
+                                               /*background_color*/ false);
+}
+
+/// @brief Set the background color of an element with linear-gradient effect.
+/// @param gradient The gradient effect to be applied on the output element.
+/// @param child The input element.
+/// @return The output element colored.
+/// @ingroup dom
+///
+/// ### Example
+///
+/// ```cpp
+/// bgcolor(LinearGradient{0, {Color::Red, Color::Blue}}, text("Hello"))
+/// ```
+Element bgcolor(const LinearGradient& gradient, Element child) {
+  return std::make_shared<LinearGradientColor>(std::move(child), gradient,
+                                               /*background_color*/ true);
+}
+
+/// @brief Decorate using a linear-gradient effect on the foreground color.
+/// @param gradient The gradient effect to be applied on the output element.
+/// @return The Decorator applying the color.
+/// @ingroup dom
+///
+/// ### Example
+///
+/// ```cpp
+/// text("Hello") | color(LinearGradient{0, {Color::Red, Color::Blue}})
+/// ```
+Decorator color(const LinearGradient& gradient) {
+  return
+      [gradient](Element child) { return color(gradient, std::move(child)); };
+}
+
+/// @brief Decorate using a linear-gradient effect on the background color.
+/// @param gradient The gradient effect to be applied on the output element.
+/// @return The Decorator applying the color.
+/// @ingroup dom
+///
+/// ### Example
+///
+/// ```cpp
+/// text("Hello") | color(LinearGradient{0, {Color::Red, Color::Blue}})
+/// ```
+Decorator bgcolor(const LinearGradient& gradient) {
+  return
+      [gradient](Element child) { return bgcolor(gradient, std::move(child)); };
+}
+
+}  // namespace ftxui
+
+// Copyright 2023 Arthur Sonzogni. All rights reserved.
+// Use of this source code is governed by the MIT license that can be found in
+// the LICENSE file.
diff --git a/src/ftxui/dom/linear_gradient_test.cpp b/src/ftxui/dom/linear_gradient_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4f3d102e497c6256ba855b1503b5126be7a0ebc8
--- /dev/null
+++ b/src/ftxui/dom/linear_gradient_test.cpp
@@ -0,0 +1,90 @@
+#include <gtest/gtest.h>  // for Test, EXPECT_EQ, Message, TestPartResult, TestInfo (ptr only), TEST
+#include <ftxui/dom/linear_gradient.hpp>  // for LinearGradient::Stop, LinearGradient
+#include <string>                         // for allocator
+
+#include "ftxui/dom/elements.hpp"  // for operator|, text, bgcolor, color, Element
+#include "ftxui/dom/node.hpp"      // for Render
+#include "ftxui/screen/color.hpp"   // for Color, Color::Red, Color::RedLight
+#include "ftxui/screen/screen.hpp"  // for Screen, Pixel
+
+namespace ftxui {
+
+TEST(ColorTest, API_default) {
+  LinearGradient gradient;
+  EXPECT_EQ(gradient.angle, 0);
+  EXPECT_EQ(gradient.stops.size(), 0);
+}
+
+TEST(ColorTest, API_builder) {
+  auto gradient = LinearGradient()  //
+                      .Angle(45)
+                      .Stop(Color::Red)
+                      .Stop(Color::RedLight, 0.5)
+                      .Stop(Color::RedLight);
+  EXPECT_EQ(gradient.angle, 45);
+  EXPECT_EQ(gradient.stops.size(), 3);
+  EXPECT_EQ(gradient.stops[0].color, Color::Red);
+  EXPECT_EQ(gradient.stops[0].position, std::nullopt);
+  EXPECT_EQ(gradient.stops[1].color, Color::RedLight);
+  EXPECT_EQ(gradient.stops[1].position, 0.5);
+  EXPECT_EQ(gradient.stops[2].color, Color::RedLight);
+  EXPECT_EQ(gradient.stops[2].position, std::nullopt);
+}
+
+TEST(ColorTest, API_constructor_bicolor) {
+  auto gradient = LinearGradient(Color::Red, Color::RedLight);
+  EXPECT_EQ(gradient.angle, 0);
+  EXPECT_EQ(gradient.stops.size(), 2);
+  EXPECT_EQ(gradient.stops[0].color, Color::Red);
+  EXPECT_EQ(gradient.stops[0].position, std::nullopt);
+  EXPECT_EQ(gradient.stops[1].color, Color::RedLight);
+  EXPECT_EQ(gradient.stops[1].position, std::nullopt);
+}
+
+TEST(ColorTest, API_constructor_bicolor_angle) {
+  auto gradient = LinearGradient(45, Color::Red, Color::RedLight);
+  EXPECT_EQ(gradient.angle, 45);
+  EXPECT_EQ(gradient.stops.size(), 2);
+  EXPECT_EQ(gradient.stops[0].color, Color::Red);
+  EXPECT_EQ(gradient.stops[0].position, std::nullopt);
+  EXPECT_EQ(gradient.stops[1].color, Color::RedLight);
+  EXPECT_EQ(gradient.stops[1].position, std::nullopt);
+}
+
+TEST(ColorTest, GradientForeground) {
+  auto element =
+      text("text") | color(LinearGradient(Color::RedLight, Color::Red));
+  Screen screen(5, 1);
+  Render(screen, element);
+
+  Color gradient_begin = Color::Interpolate(0, Color::RedLight, Color::Red);
+  Color gradient_end = Color::Interpolate(1, Color::RedLight, Color::Red);
+
+  EXPECT_EQ(screen.PixelAt(0, 0).foreground_color, gradient_begin);
+  EXPECT_EQ(screen.PixelAt(0, 0).background_color, Color());
+
+  EXPECT_EQ(screen.PixelAt(4, 0).foreground_color, gradient_end);
+  EXPECT_EQ(screen.PixelAt(4, 0).background_color, Color());
+}
+
+TEST(ColorTest, GradientBackground) {
+  auto element =
+      text("text") | bgcolor(LinearGradient(Color::RedLight, Color::Red));
+  Screen screen(5, 1);
+  Render(screen, element);
+
+  Color gradient_begin = Color::Interpolate(0, Color::RedLight, Color::Red);
+  Color gradient_end = Color::Interpolate(1, Color::RedLight, Color::Red);
+
+  EXPECT_EQ(screen.PixelAt(0, 0).foreground_color, Color());
+  EXPECT_EQ(screen.PixelAt(0, 0).background_color, gradient_begin);
+
+  EXPECT_EQ(screen.PixelAt(4, 0).foreground_color, Color());
+  EXPECT_EQ(screen.PixelAt(4, 0).background_color, gradient_end);
+}
+
+}  // namespace ftxui
+
+// Copyright 2023 Arthur Sonzogni. All rights reserved.
+// Use of this source code is governed by the MIT license that can be found in
+// the LICENSE file.
diff --git a/src/ftxui/dom/table.cpp b/src/ftxui/dom/table.cpp
index bdaf5fc5287b3eff8775ea3cf7630ed260753c37..4de41ac88285953db698b989cc8c5db11149397c 100644
--- a/src/ftxui/dom/table.cpp
+++ b/src/ftxui/dom/table.cpp
@@ -15,12 +15,12 @@ bool IsCell(int x, int y) {
 
 // NOLINTNEXTLINE
 static std::string charset[6][6] = {
-    {"┌", "┐", "└", "┘", "─", "│"}, // LIGHT
-    {"┏", "┓", "┗", "┛", "╍", "╏"}, // DASHED
-    {"┏", "┓", "┗", "┛", "━", "┃"}, // HEAVY
-    {"╔", "╗", "╚", "╝", "═", "║"}, // DOUBLE
-    {"╭", "╮", "╰", "╯", "─", "│"}, // ROUNDED
-    {" ", " ", " ", " ", " ", " "}, // EMPTY
+    {"┌", "┐", "└", "┘", "─", "│"},  // LIGHT
+    {"┏", "┓", "┗", "┛", "╍", "╏"},  // DASHED
+    {"┏", "┓", "┗", "┛", "━", "┃"},  // HEAVY
+    {"╔", "╗", "╚", "╝", "═", "║"},  // DOUBLE
+    {"╭", "╮", "╰", "╯", "─", "│"},  // ROUNDED
+    {" ", " ", " ", " ", " ", " "},  // EMPTY
 };
 
 int Wrap(int input, int modulo) {
diff --git a/src/ftxui/screen/color.cpp b/src/ftxui/screen/color.cpp
index 30caf2c7f054cef3decbd5558d5aada76a61634a..f52180d2c6e98b5f60e582e6b9a69504be893747 100644
--- a/src/ftxui/screen/color.cpp
+++ b/src/ftxui/screen/color.cpp
@@ -1,6 +1,7 @@
 #include "ftxui/screen/color.hpp"
 
-#include <array>        // for array
+#include <array>  // for array
+#include <cmath>
 #include <string_view>  // for literals
 
 #include "ftxui/screen/color_info.hpp"  // for GetColorInfo, ColorInfo
@@ -220,12 +221,12 @@ Color Color::Interpolate(float t, const Color& a, const Color& b) {
   get_color(a, &red_a, &green_a, &blue_a);
   get_color(b, &red_b, &green_b, &blue_b);
 
-  return Color::RGB(static_cast<uint8_t>(static_cast<float>(red_a) * (1 - t) +
-                                         static_cast<float>(red_b) * t),
-                    static_cast<uint8_t>(static_cast<float>(green_a) * (1 - t) +
-                                         static_cast<float>(green_b) * t),
-                    static_cast<uint8_t>(static_cast<float>(blue_a) * (1 - t) +
-                                         static_cast<float>(blue_b) * t));
+  // Gamma correction:
+  // https://en.wikipedia.org/wiki/Gamma_correction
+  return Color::RGB(
+      pow(pow(red_a, 2.2f) * (1 - t) + pow(red_b, 2.2f) * t, 1 / 2.2f),
+      pow(pow(green_a, 2.2f) * (1 - t) + pow(green_b, 2.2f) * t, 1 / 2.2f),
+      pow(pow(blue_a, 2.2f) * (1 - t) + pow(blue_b, 2.2f) * t, 1 / 2.2f));
 }
 
 inline namespace literals {
diff --git a/src/ftxui/screen/color_test.cpp b/src/ftxui/screen/color_test.cpp
index 12dbb2838dc4ee8294317bdae753d75c8a23ab2b..4dc65dfd079481384294ab37c49eb79f562a24a2 100644
--- a/src/ftxui/screen/color_test.cpp
+++ b/src/ftxui/screen/color_test.cpp
@@ -57,22 +57,22 @@ TEST(ColorTest, Interpolate) {
                                Color::RGB(1, 2, 3),        //
                                Color::RGB(244, 244, 123))  //
                 .Print(false),
-            "38;2;73;74;39");
+            "38;2;141;141;71");
   EXPECT_EQ(Color::Interpolate(0.7f,                       //
                                Color::RGB(1, 2, 3),        //
                                Color::RGB(244, 244, 123))  //
                 .Print(false),
-            "38;2;171;171;87");
+            "38;2;207;207;104");
   EXPECT_EQ(Color::Interpolate(0.7f,                       //
                                Color(Color::Red),          //
                                Color::RGB(244, 244, 123))  //
                 .Print(false),
-            "38;2;209;170;86");
+            "38;2;216;207;104");
   EXPECT_EQ(Color::Interpolate(0.7f,                       //
                                Color::RGB(244, 244, 123),  //
                                Color(Color::Plum1))        //
                 .Print(false),
-            "38;2;251;195;215");
+            "38;2;251;198;225");
 }
 
 TEST(ColorTest, HSV) {