diff --git a/addons/sale/static/src/scss/product_configurator.scss b/addons/sale/static/src/scss/product_configurator.scss
index 7538018795a61db259fe19dd0bf10edcae41e72f..2044539eb6f006d2e595728bc99ed3e8bab8aac2 100644
--- a/addons/sale/static/src/scss/product_configurator.scss
+++ b/addons/sale/static/src/scss/product_configurator.scss
@@ -31,6 +31,10 @@
     &.custom_value {
         background-image: linear-gradient(to bottom right, #FF0000, #FFF200, #1E9600);
     }
+
+    &.transparent {
+        background-image: url(/web/static/img/transparent.png);
+    }
 }
 
 .css_not_available_msg {
diff --git a/addons/sale/views/variant_templates.xml b/addons/sale/views/variant_templates.xml
index bca394f00bde32a8f51dba3dd8c44dbafa870609..af0d8674ab69f9a63a23c4a0d4f16b00e4b529ab 100644
--- a/addons/sale/views/variant_templates.xml
+++ b/addons/sale/views/variant_templates.xml
@@ -95,7 +95,7 @@
                         <ul t-att-data-attribute_id="ptal.attribute_id.id" t-attf-class="list-inline o_wsale_product_attribute #{'d-none' if single_and_custom else ''}">
                             <li t-foreach="ptal.product_template_value_ids._only_active()" t-as="ptav" class="list-inline-item me-1">
                                 <label t-attf-style="background-color:#{ptav.html_color or ptav.product_attribute_value_id.name if not ptav.is_custom else ''}"
-                                    t-attf-class="css_attribute_color #{'active' if ptav in combination else ''} #{'custom_value' if ptav.is_custom else ''}">
+                                    t-attf-class="css_attribute_color #{'active' if ptav in combination else ''} #{'custom_value' if ptav.is_custom else ''} #{'transparent' if (not ptav.is_custom and not ptav.html_color) else ''}">
                                     <input type="radio"
                                         t-attf-class="js_variant_change  #{ptal.attribute_id.create_variant}"
                                         t-att-checked="ptav in combination"
diff --git a/addons/web/static/src/views/fields/color/color_field.js b/addons/web/static/src/views/fields/color/color_field.js
index 852df48ed485e3e33259c0dffd7fc2a004f361fe..afd51f6de1e74b555e600b7bea035d1c606664d1 100644
--- a/addons/web/static/src/views/fields/color/color_field.js
+++ b/addons/web/static/src/views/fields/color/color_field.js
@@ -8,11 +8,11 @@ import { Component, useState, onWillUpdateProps } from "@odoo/owl";
 export class ColorField extends Component {
     setup() {
         this.state = useState({
-            color: this.props.value || "#000000",
+            color: this.props.value || '',
         });
 
         onWillUpdateProps((nextProps) => {
-            this.state.color = nextProps.value || "#000000";
+            this.state.color = nextProps.value || '';
         });
     }
 
diff --git a/addons/web/static/src/views/fields/color/color_field.xml b/addons/web/static/src/views/fields/color/color_field.xml
index b30b0534f09d607b891eb70d35e29e5275c0d771..46a47d119dcc702e48206ab8c385fb5e95797d90 100644
--- a/addons/web/static/src/views/fields/color/color_field.xml
+++ b/addons/web/static/src/views/fields/color/color_field.xml
@@ -2,8 +2,8 @@
 <templates xml:space="preserve">
 
     <t t-name="web.ColorField" owl="1">
-        <div class="o_field_color d-flex" t-att-class="{ 'o_field_cursor_disabled': readonly }" t-attf-style="background-color: {{state.color}}">
-            <input t-on-click.stop="" class="w-100 h-100 opacity-0" type="color" t-att-value="state.color" t-att-disabled="readonly" t-on-input="(ev) => this.state.color = ev.target.value" t-on-change="(ev) => this.props.update(ev.target.value)" />
+        <div class="o_field_color d-flex" t-att-class="{ 'o_field_cursor_disabled': isReadonly }" t-attf-style="background: #{state.color or 'url(/web/static/img/transparent.png)'}">
+            <input t-on-click.stop="" class="w-100 h-100 opacity-0" type="color" t-att-value="state.color" t-att-disabled="isReadonly" t-on-input="(ev) => this.state.color = ev.target.value" t-on-change="(ev) => this.props.update(ev.target.value)" />
         </div>
     </t>
 
diff --git a/addons/web/static/tests/views/fields/color_field_tests.js b/addons/web/static/tests/views/fields/color_field_tests.js
index abab67061d0c37f720e0a2f602177f9986198020..f71c5572e94e4623b3f92269072a4f3845028667 100644
--- a/addons/web/static/tests/views/fields/color_field_tests.js
+++ b/addons/web/static/tests/views/fields/color_field_tests.js
@@ -61,8 +61,8 @@ QUnit.module("Fields", (hooks) => {
         // style returns the value in the rgb format
         assert.strictEqual(
             target.querySelector(".o_field_color div").style.backgroundColor,
-            "rgb(0, 0, 0)",
-            "field has the default color set as background if no value has been selected"
+            "initial",
+            "field has the transparent background if no color value has been selected"
         );
 
         assert.strictEqual(target.querySelector(".o_field_color input").value, "#000000");
@@ -100,6 +100,25 @@ QUnit.module("Fields", (hooks) => {
         assert.doesNotHaveClass(target.querySelector(".o_data_row"), "o_selected_row");
     });
 
+    QUnit.test("read-only color field in editable list view", async function (assert) {
+        await makeView({
+            type: "list",
+            serverData,
+            resModel: "partner",
+            arch: `
+                <tree editable="bottom">
+                    <field name="hex_color" readonly="1" widget="color" />
+                </tree>`,
+        });
+
+        assert.containsN(
+            target,
+            '.o_field_color input:disabled',
+            2,
+            "the field should not be editable"
+        );
+    });
+
     QUnit.test("color field change via another field's onchange", async (assert) => {
         serverData.models.partner.onchanges = {
             foo: (rec) => {
@@ -125,8 +144,8 @@ QUnit.module("Fields", (hooks) => {
 
         assert.strictEqual(
             target.querySelector(".o_field_color div").style.backgroundColor,
-            "rgb(0, 0, 0)",
-            "field has the default color set as background if no value has been selected"
+            "initial",
+            "field has transparent background if no color value has been selected"
         );
         assert.strictEqual(target.querySelector(".o_field_color input").value, "#000000");
         await editInput(target, ".o_field_char[name='foo'] input", "someValue");