Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LibWeb/CSS: Implement the color-scheme CSS property #3146

Merged
merged 4 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions Base/res/ladybird/inspector.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

@media (prefers-color-scheme: dark) {
:root {
--background: rgb(23, 23, 23);
--separator: dimgray;
--separator-accent: rgb(57, 57, 57);
--tab-controls: rgb(57, 57, 57);
Expand All @@ -30,7 +29,6 @@

@media (prefers-color-scheme: light) {
:root {
--background: white;
--separator: lightgray;
--separator-accent: white;
--tab-controls: rgb(229, 229, 229);
Expand All @@ -54,7 +52,7 @@
}

html {
background-color: var(--background);
color-scheme: light dark;
}

body {
Expand Down Expand Up @@ -186,7 +184,7 @@ body {
left: 0;
right: 0;
background-color: var(--tab-controls);
border-top: 2px solid var(--background);
border-top: 2px solid Canvas;
display: flex;
padding: 0.5em;
}
Expand Down
7 changes: 2 additions & 5 deletions Base/res/ladybird/newtab.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
<meta charset="UTF-8">
<title>New Tab</title>
<style>
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
@media (prefers-color-scheme: dark) {
html {
background-color: rgb(20, 20, 20);
}
html {
color-scheme: light dark;
}
</style>
</head>
Expand Down
11 changes: 2 additions & 9 deletions Base/res/ladybird/templates/directory.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,8 @@
<meta charset="UTF-8">
<title>Index of %path%</title>
<style>
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
@media (prefers-color-scheme: dark) {
html {
background-color: rgb(20, 20, 20);
color: rgb(235, 235, 235);
}
a {
color: cornflowerblue;
}
html {
color-scheme: light dark;
}

header {
Expand Down
8 changes: 2 additions & 6 deletions Base/res/ladybird/templates/error.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@
<meta charset="UTF-8">
<title>Error!</title>
<style>
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
@media (prefers-color-scheme: dark) {
html {
background-color: rgb(20, 20, 20);
color: rgb(235, 235, 235);
}
html {
color-scheme: light dark;
}

h1 {
Expand Down
8 changes: 2 additions & 6 deletions Base/res/ladybird/templates/version.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@
<meta charset="UTF-8">
<title>About %browser_name%</title>
<style>
/* FIXME: We should be able to remove the HTML style when "color-scheme" is supported */
@media (prefers-color-scheme: dark) {
html {
background-color: rgb(20, 20, 20);
color: rgb(235, 235, 235);
}
html {
color-scheme: light dark;
}
img {
float: left;
Expand Down
2 changes: 2 additions & 0 deletions Libraries/LibWeb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ set(SOURCES
CSS/StyleValues/BasicShapeStyleValue.cpp
CSS/StyleValues/BorderRadiusStyleValue.cpp
CSS/StyleValues/CalculatedStyleValue.cpp
CSS/StyleValues/ColorSchemeStyleValue.cpp
CSS/StyleValues/ConicGradientStyleValue.cpp
CSS/StyleValues/ContentStyleValue.cpp
CSS/StyleValues/CounterDefinitionsStyleValue.cpp
Expand All @@ -137,6 +138,7 @@ set(SOURCES
CSS/StyleValues/CSSKeywordValue.cpp
CSS/StyleValues/CSSLabLike.cpp
CSS/StyleValues/CSSLCHLike.cpp
CSS/StyleValues/CSSLightDark.cpp
CSS/StyleValues/CSSRGB.cpp
CSS/StyleValues/DisplayStyleValue.cpp
CSS/StyleValues/EasingStyleValue.cpp
Expand Down
7 changes: 7 additions & 0 deletions Libraries/LibWeb/CSS/CSSStyleValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <LibWeb/CSS/StyleValues/CSSColorValue.h>
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
#include <LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h>
#include <LibWeb/CSS/StyleValues/ConicGradientStyleValue.h>
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
Expand Down Expand Up @@ -116,6 +117,12 @@ CSSColorValue const& CSSStyleValue::as_color() const
return static_cast<CSSColorValue const&>(*this);
}

ColorSchemeStyleValue const& CSSStyleValue::as_color_scheme() const
{
VERIFY(is_color_scheme());
return static_cast<ColorSchemeStyleValue const&>(*this);
}

ConicGradientStyleValue const& CSSStyleValue::as_conic_gradient() const
{
VERIFY(is_conic_gradient());
Expand Down
5 changes: 5 additions & 0 deletions Libraries/LibWeb/CSS/CSSStyleValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class CSSStyleValue : public RefCounted<CSSStyleValue> {
BorderRadius,
Calculated,
Color,
ColorScheme,
ConicGradient,
Content,
Counter,
Expand Down Expand Up @@ -178,6 +179,10 @@ class CSSStyleValue : public RefCounted<CSSStyleValue> {
CSSColorValue const& as_color() const;
CSSColorValue& as_color() { return const_cast<CSSColorValue&>(const_cast<CSSStyleValue const&>(*this).as_color()); }

bool is_color_scheme() const { return type() == Type::ColorScheme; }
ColorSchemeStyleValue const& as_color_scheme() const;
ColorSchemeStyleValue& as_color_scheme() { return const_cast<ColorSchemeStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_color_scheme()); }

bool is_conic_gradient() const { return type() == Type::ConicGradient; }
ConicGradientStyleValue const& as_conic_gradient() const;
ConicGradientStyleValue& as_conic_gradient() { return const_cast<ConicGradientStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_conic_gradient()); }
Expand Down
39 changes: 39 additions & 0 deletions Libraries/LibWeb/CSS/ComputedProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <LibWeb/CSS/ComputedProperties.h>
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
#include <LibWeb/CSS/StyleValues/ColorSchemeStyleValue.h>
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
#include <LibWeb/CSS/StyleValues/CounterStyleValue.h>
Expand Down Expand Up @@ -228,6 +229,44 @@ Color ComputedProperties::color_or_fallback(CSS::PropertyID id, Layout::NodeWith
return value.to_color(node);
}

// https://drafts.csswg.org/css-color-adjust-1/#determine-the-used-color-scheme
CSS::PreferredColorScheme ComputedProperties::color_scheme(CSS::PreferredColorScheme preferred_scheme, Optional<Vector<String> const&> document_supported_schemes) const
{
// To determine the used color scheme of an element:
auto const& scheme_value = property(CSS::PropertyID::ColorScheme).as_color_scheme();

// 1. If the user’s preferred color scheme, as indicated by the prefers-color-scheme media feature,
// is present among the listed color schemes, and is supported by the user agent,
// that’s the element’s used color scheme.
if (preferred_scheme != CSS::PreferredColorScheme::Auto && scheme_value.schemes().contains_slow(preferred_color_scheme_to_string(preferred_scheme)))
return preferred_scheme;

// 2. Otherwise, if the user has indicated an overriding preference for their chosen color scheme,
// and the only keyword is not present in color-scheme for the element,
// the user agent must override the color scheme with the user’s preferred color scheme.
// See § 2.3 Overriding the Color Scheme.
// FIXME: We don't currently support setting an "overriding preference" for color schemes.

// 3. Otherwise, if the user agent supports at least one of the listed color schemes,
// the used color scheme is the first supported color scheme in the list.
auto first_supported = scheme_value.schemes().first_matching([](auto scheme) { return preferred_color_scheme_from_string(scheme) != CSS::PreferredColorScheme::Auto; });
if (first_supported.has_value())
return preferred_color_scheme_from_string(first_supported.value());

// 4. Otherwise, the used color scheme is the browser default. (Same as normal.)
// `normal` indicates that the element supports the page’s supported color schemes, if they are set
if (document_supported_schemes.has_value()) {
if (preferred_scheme != CSS::PreferredColorScheme::Auto && document_supported_schemes->contains_slow(preferred_color_scheme_to_string(preferred_scheme)))
return preferred_scheme;

auto document_first_supported = document_supported_schemes->first_matching([](auto scheme) { return preferred_color_scheme_from_string(scheme) != CSS::PreferredColorScheme::Auto; });
if (document_first_supported.has_value())
return preferred_color_scheme_from_string(document_first_supported.value());
}

return CSS::PreferredColorScheme::Light;
}

NonnullRefPtr<Gfx::Font const> ComputedProperties::font_fallback(bool monospace, bool bold, float point_size)
{
if (monospace && bold)
Expand Down
1 change: 1 addition & 0 deletions Libraries/LibWeb/CSS/ComputedProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class ComputedProperties final : public JS::Cell {
Optional<LengthPercentage> length_percentage(CSS::PropertyID) const;
LengthBox length_box(CSS::PropertyID left_id, CSS::PropertyID top_id, CSS::PropertyID right_id, CSS::PropertyID bottom_id, const CSS::Length& default_value) const;
Color color_or_fallback(CSS::PropertyID, Layout::NodeWithStyle const&, Color fallback) const;
CSS::PreferredColorScheme color_scheme(CSS::PreferredColorScheme, Optional<Vector<String> const&> document_supported_schemes) const;
Optional<CSS::TextAnchor> text_anchor() const;
Optional<CSS::TextAlign> text_align() const;
Optional<CSS::TextJustify> text_justify() const;
Expand Down
5 changes: 5 additions & 0 deletions Libraries/LibWeb/CSS/ComputedValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <LibWeb/CSS/GridTrackSize.h>
#include <LibWeb/CSS/LengthBox.h>
#include <LibWeb/CSS/PercentageOr.h>
#include <LibWeb/CSS/PreferredColorScheme.h>
#include <LibWeb/CSS/Ratio.h>
#include <LibWeb/CSS/Size.h>
#include <LibWeb/CSS/StyleValues/AbstractImageStyleValue.h>
Expand Down Expand Up @@ -76,6 +77,7 @@ class InitialValues {
static CSS::CaptionSide caption_side() { return CSS::CaptionSide::Top; }
static CSS::Clear clear() { return CSS::Clear::None; }
static CSS::Clip clip() { return CSS::Clip::make_auto(); }
static CSS::PreferredColorScheme color_scheme() { return CSS::PreferredColorScheme::Auto; }
static CSS::ContentVisibility content_visibility() { return CSS::ContentVisibility::Visible; }
static CSS::Cursor cursor() { return CSS::Cursor::Auto; }
static CSS::WhiteSpace white_space() { return CSS::WhiteSpace::Normal; }
Expand Down Expand Up @@ -351,6 +353,7 @@ class ComputedValues {
CSS::CaptionSide caption_side() const { return m_inherited.caption_side; }
CSS::Clear clear() const { return m_noninherited.clear; }
CSS::Clip clip() const { return m_noninherited.clip; }
CSS::PreferredColorScheme color_scheme() const { return m_inherited.color_scheme; }
CSS::ContentVisibility content_visibility() const { return m_inherited.content_visibility; }
CSS::Cursor cursor() const { return m_inherited.cursor; }
CSS::ContentData content() const { return m_noninherited.content; }
Expand Down Expand Up @@ -543,6 +546,7 @@ class ComputedValues {
CSS::Length border_spacing_vertical { InitialValues::border_spacing() };
CSS::CaptionSide caption_side { InitialValues::caption_side() };
Color color { InitialValues::color() };
CSS::PreferredColorScheme color_scheme { InitialValues::color_scheme() };
Optional<Color> accent_color {};
Color webkit_text_fill_color { InitialValues::color() };
CSS::ContentVisibility content_visibility { InitialValues::content_visibility() };
Expand Down Expand Up @@ -724,6 +728,7 @@ class MutableComputedValues final : public ComputedValues {
void set_border_spacing_vertical(CSS::Length border_spacing_vertical) { m_inherited.border_spacing_vertical = border_spacing_vertical; }
void set_caption_side(CSS::CaptionSide caption_side) { m_inherited.caption_side = caption_side; }
void set_color(Color color) { m_inherited.color = color; }
void set_color_scheme(CSS::PreferredColorScheme color_scheme) { m_inherited.color_scheme = color_scheme; }
void set_clip(CSS::Clip const& clip) { m_noninherited.clip = clip; }
void set_content(ContentData const& content) { m_noninherited.content = content; }
void set_content_visibility(CSS::ContentVisibility content_visibility) { m_inherited.content_visibility = content_visibility; }
Expand Down
22 changes: 8 additions & 14 deletions Libraries/LibWeb/CSS/Default.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

html {
font-family: serif;
color: CanvasText;
}

body {
Expand Down Expand Up @@ -54,27 +53,20 @@ button, input[type=submit], input[type=button], input[type=reset], select, ::fil
border: 1px solid ButtonBorder;
color: ButtonText;
cursor: default;
/* FIXME: For some reason this filter is required for the :hover style to work */
filter: contrast(100%);
}

button:disabled, input[type=submit]:disabled, input[type=button]:disabled, input[type=reset]:disabled, select:disabled {
/* FIXME: There isn't a <system-color> keyword for this, so this is a slightly lightened
* version of our light ButtonFace color. Once we support `color-scheme: dark`
* we'll need to use a different color for that.
*/
background-color: #e5e0d7;
color: GrayText;
filter: contrast(70%);
}

input[type=image] {
cursor: pointer;
}

button:hover, input[type=submit]:hover, input[type=button]:hover, input[type=reset]:hover, select:hover {
/* FIXME: There isn't a <system-color> keyword for this, so this is a slightly lightened
* version of our light ButtonFace color. Once we support `color-scheme: dark`
* we'll need to use a different color for that.
*/
background-color: #e5e0d7;
filter: contrast(70%);
}

option {
Expand All @@ -95,7 +87,7 @@ input[type=range]::-webkit-slider-runnable-track {
height: 4px;
width: 100%;
margin-top: 6px;
background-color: Background;
background-color: AccentColorText;
AtkinsSJ marked this conversation as resolved.
Show resolved Hide resolved
border: 1px solid rgba(0, 0, 0, 0.5);
}
input[type=range]::-webkit-slider-thumb {
Expand Down Expand Up @@ -143,7 +135,7 @@ progress::-webkit-progress-bar, progress::-webkit-progress-value {
height: 100%;
}
progress::-webkit-progress-bar {
background-color: Background;
background-color: AccentColorText;
border: 1px solid rgba(0, 0, 0, 0.5);
}

Expand Down Expand Up @@ -862,6 +854,8 @@ progress {
/* https://github.com/whatwg/html/pull/9546
*/
input[type=checkbox][switch] {
/* FIXME: Workaround until we can properly style dark switches */
color-scheme: light;
appearance: none;
height: 1em;
width: 1.8em;
Expand Down
Loading
Loading