diff --git a/src/channel.js b/src/channel.js
index 314861599c..100688908f 100644
--- a/src/channel.js
+++ b/src/channel.js
@@ -51,6 +51,7 @@ export function inferChannelScale(name, channel) {
break;
case "fillOpacity":
case "strokeOpacity":
+ case "opacity":
channel.scale = scale !== true && isEvery(value, isOpacity) ? null : "opacity";
break;
case "symbol":
diff --git a/test/output/opacityDotsFillUnscaled.svg b/test/output/opacityDotsFillUnscaled.svg
new file mode 100644
index 0000000000..e91513913b
--- /dev/null
+++ b/test/output/opacityDotsFillUnscaled.svg
@@ -0,0 +1,81 @@
+
\ No newline at end of file
diff --git a/test/output/opacityDotsStrokeUnscaled.svg b/test/output/opacityDotsStrokeUnscaled.svg
new file mode 100644
index 0000000000..49481b911f
--- /dev/null
+++ b/test/output/opacityDotsStrokeUnscaled.svg
@@ -0,0 +1,81 @@
+
\ No newline at end of file
diff --git a/test/output/opacityDotsUnscaled.svg b/test/output/opacityDotsUnscaled.svg
new file mode 100644
index 0000000000..f47189b453
--- /dev/null
+++ b/test/output/opacityDotsUnscaled.svg
@@ -0,0 +1,81 @@
+
\ No newline at end of file
diff --git a/test/plots/index.ts b/test/plots/index.ts
index fd35318b1b..39d3b5b461 100644
--- a/test/plots/index.ts
+++ b/test/plots/index.ts
@@ -164,6 +164,7 @@ export * from "./movies-rating-by-genre.js";
export * from "./multiplication-table.js";
export * from "./music-revenue.js";
export * from "./npm-versions.js";
+export * from "./opacity.js";
export * from "./ordinal-bar.js";
export * from "./penguin-annotated.js";
export * from "./penguin-culmen-array.js";
diff --git a/test/plots/opacity.ts b/test/plots/opacity.ts
new file mode 100644
index 0000000000..6db86e1281
--- /dev/null
+++ b/test/plots/opacity.ts
@@ -0,0 +1,27 @@
+import * as d3 from "d3";
+import * as Plot from "@observablehq/plot";
+
+export function opacityDotsFillUnscaled() {
+ return Plot.dotX(d3.ticks(0.3, 0.7, 40), {
+ fill: "black",
+ r: 7,
+ fillOpacity: Plot.identity
+ }).plot();
+}
+
+export function opacityDotsStrokeUnscaled() {
+ return Plot.dotX(d3.ticks(0.3, 0.7, 40), {
+ stroke: "black",
+ r: 3.5,
+ strokeWidth: 7,
+ strokeOpacity: Plot.identity
+ }).plot();
+}
+
+export function opacityDotsUnscaled() {
+ return Plot.dotX(d3.ticks(0.3, 0.7, 40), {
+ fill: "black",
+ r: 7,
+ opacity: Plot.identity
+ }).plot();
+}