Skip to content

Add injectStyles, so Dropzone can supply its own CSS - #2363

Open
enyo wants to merge 1 commit into
mainfrom
inject-css
Open

enyo wants to merge 1 commit into
mainfrom
inject-css

Conversation

@enyo

@enyo enyo commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Stacked on #2362. Setting injectStyles makes Dropzone insert dropzone.css into the document itself — no <link> to remember, no path to keep in step with the package.

new Dropzone("#my-form", { url: "/file/post", injectStyles: true });

The CSS is carried as a string rather than imported for its side effect, so nothing reaches the document unless the option asks for it.

Two decisions worth reviewing

It is prepended to <head>, not appended. Appending would place it after a stylesheet the page already links, so turning the option on would quietly override styling that used to work. Prepending means your rules keep winning on equal specificity, with no !important. There is a test for the ordering, because it is the kind of thing a later refactor silently reverses.

It runs before the fallback check, since the fallback form is styled by the same stylesheet.

The cost, stated plainly

injectStyles defaults to false, and this is why: the stylesheet travels inside the JavaScript bundle whether or not the option is switched on, because a runtime condition cannot be tree-shaken.

before after
dropzone-min.js 37,755 B 42,668 B
gzipped 11,767 B 13,066 B

That is +1.3 kB gzipped, about 11%, paid by everyone. Anyone importing the CSS through a bundler should keep doing that — it stays the smaller option, and the docs say so. This is for the people who would otherwise ship no stylesheet at all.

If that cost turns out to bother you, the alternative is a separate entry point (dropzone/with-styles) that only its importers pay for — but that is an import, not an option, which is not what you asked for.

Tests

7 unit tests and 2 end-to-end. The end-to-end ones matter more than usual: the page they load links no stylesheet at all, and the assertion is a computed min-height of 150px. That proves the CSS survived bundling into the standalone file and is actually applying — not merely that a <style> element appeared.

259 unit tests and 5 end-to-end specs pass overall. The docs are updated in both places: a row in the options table, and a section under Installation → CSS that includes the size tradeoff.

A fix that belongs to #2362

While building this I found #2362's CI failing on format:check for src/dropzone.css. Cause: oxfmt runs with --ignore-path .gitignore, and the stale src/.gitignore I deleted in that pull request had been hiding the file from the formatter as well as from git. Fixed on that branch, not this one, and this branch was rebased onto it.

@github-actions

github-actions Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 79.6% 890 / 1118
🔵 Statements 79.82% 938 / 1175
🔵 Functions 92.92% 197 / 212
🔵 Branches 76.61% 521 / 680
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/dropzone/src/dropzone.ts 77.5% 75.08% 92.68% 77.16% 250, 260, 285, 291-294, 351, 378, 421-422, 481, 589, 611, 630-631, 738, 761-764, 801-803, 833-836, 859, 1005, 1033, 1062, 1066, 1138-1139, 1171, 1181-1183, 1200-1201, 1207-1240, 1354, 1412, 1461-1462, 1590, 1614-1615, 1669, 1703, 1723-1754, 1762, 1776-1780, 1791, 1804-1809, 1822-1823, 1827-1828, 1846-1847, 1925-1940, 1985, 2001, 2035, 2036, 2191-2193, 2228, 2238, 2271-2305, 2312-2413, 2422-2425
packages/dropzone/src/options.ts 89.91% 76% 92.68% 89.83% 479, 501-504, 516-517, 582, 700, 741, 767, 784
packages/dropzone/src/types.d.ts 0% 0% 0% 0%
Generated in workflow #138 for commit 45dbe92 by the Vitest Coverage Report Action

Setting injectStyles makes Dropzone insert its stylesheet into the document
itself, so there is no link tag to remember and no path to keep in step with
the package. It takes which one:

  false            add nothing, the default
  true or "full"   dropzone.css, the ready-to-go styling
  "basic"          basic.css, layout only

They are alternatives rather than layers, which is the reason the option
names them rather than counting them: basic.css is not a subset of
dropzone.css. Twenty of its thirty-five declarations are absent from the full
sheet, including `position: relative` on .dropzone -- the full theme
positions against .dz-preview instead -- along with the progress bar and the
success and error marks. Picking one excludes the other, so a name like "all"
would have been a lie.

The stylesheets are carried as strings rather than imported for their side
effect, so nothing reaches the document unless the option asks for it.

It is inserted once per page however many dropzones exist, and prepended to
head rather than appended. Appending would put it after a stylesheet the page
already links, so switching the option on would quietly override styling that
used to work. Prepending means page rules keep winning on equal specificity.
The style element is tagged with which variant went in, so a second dropzone
asking for the other can be seen to have been ignored rather than silently
doubling up.

It runs before the fallback check, because the fallback form is styled by the
same stylesheet.

Defaults to false, and this is the tradeoff worth stating plainly: both
stylesheets travel inside the JavaScript bundle whether or not the option is
on, because a runtime condition cannot be tree-shaken. That is 1.4 kB
gzipped, on a bundle that was 11.8 kB. Anyone importing the CSS through a
bundler should keep doing that; this is for the people who would otherwise
ship no stylesheet at all.

The end-to-end tests load pages with no stylesheet link whatsoever and assert
computed values that only one of the two sheets can produce, so they prove
the right CSS survived bundling into the standalone file rather than merely
that a style element appeared.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant