diff --git a/dask/dataframe/io/csv.py b/dask/dataframe/io/csv.py
--- a/dask/dataframe/io/csv.py
+++ b/dask/dataframe/io/csv.py
@@ -30,6 +30,8 @@
 
 import fsspec.implementations.local
 from fsspec.compression import compr
+from fsspec.core import get_fs_token_paths
+from fsspec.utils import infer_compression
 
 
 class CSVSubgraph(Mapping):
@@ -456,7 +458,7 @@ def read_pandas(
     urlpath,
     blocksize="default",
     lineterminator=None,
-    compression=None,
+    compression="infer",
     sample=256000,
     enforce=False,
     assume_missing=False,
@@ -508,6 +510,15 @@ def read_pandas(
     else:
         path_converter = None
 
+    # If compression is "infer", inspect the (first) path suffix and
+    # set the proper compression option if the suffix is recongnized.
+    if compression == "infer":
+        # Translate the input urlpath to a simple path list
+        paths = get_fs_token_paths(urlpath, mode="rb", storage_options=kwargs)[2]
+
+        # Infer compression from first path
+        compression = infer_compression(paths[0])
+
     if blocksize == "default":
         blocksize = AUTO_BLOCKSIZE
     if isinstance(blocksize, str):
@@ -688,7 +699,7 @@ def read(
         urlpath,
         blocksize="default",
         lineterminator=None,
-        compression=None,
+        compression="infer",
         sample=256000,
         enforce=False,
         assume_missing=False,

I can think of no good reason for the difference.
Note that decompression could happen within fsspec *or* pandas, but both should amount to the same thing.
diff --git a/dask/dataframe/io/tests/test_csv.py b/dask/dataframe/io/tests/test_csv.py
--- a/dask/dataframe/io/tests/test_csv.py
+++ b/dask/dataframe/io/tests/test_csv.py
@@ -28,8 +28,8 @@
 from dask.utils import filetexts, filetext, tmpfile, tmpdir
 from fsspec.compression import compr
 
-
-fmt_bs = [(fmt, None) for fmt in compr] + [(fmt, 10) for fmt in compr]
+# List of available compression format for test_read_csv_compression
+compression_fmts = [fmt for fmt in compr] + [None]
 
 
 def normalize_text(s):
@@ -680,7 +680,8 @@ def test_categorical_known():
 
 
 @pytest.mark.slow
-def test_compression_multiple_files():
+@pytest.mark.parametrize("compression", ["infer", "gzip"])
+def test_compression_multiple_files(compression):
     with tmpdir() as tdir:
         f = gzip.open(os.path.join(tdir, "a.csv.gz"), "wb")
         f.write(csv_text.encode())
@@ -691,7 +692,7 @@ def test_compression_multiple_files():
         f.close()
 
         with pytest.warns(UserWarning):
-            df = dd.read_csv(os.path.join(tdir, "*.csv.gz"), compression="gzip")
+            df = dd.read_csv(os.path.join(tdir, "*.csv.gz"), compression=compression)
 
         assert len(df.compute()) == (len(csv_text.split("\n")) - 1) * 2
 
@@ -716,17 +717,22 @@ def test_read_csv_sensitive_to_enforce():
         assert a._name != b._name
 
 
-@pytest.mark.parametrize("fmt,blocksize", fmt_bs)
+@pytest.mark.parametrize("blocksize", [None, 10])
+@pytest.mark.parametrize("fmt", compression_fmts)
 def test_read_csv_compression(fmt, blocksize):
-    if fmt not in compress:
+    if fmt and fmt not in compress:
         pytest.skip("compress function not provided for %s" % fmt)
-    files2 = valmap(compress[fmt], csv_files)
-    with filetexts(files2, mode="b"):
+    suffix = {"gzip": ".gz", "bz2": ".bz2", "zip": ".zip", "xz": ".xz"}.get(fmt, "")
+    files2 = valmap(compress[fmt], csv_files) if fmt else csv_files
+    renamed_files = {k + suffix: v for k, v in files2.items()}
+    with filetexts(renamed_files, mode="b"):
+        # This test is using `compression="infer"` (the default) for
+        # read_csv.  The paths must have the appropriate extension.
         if fmt and blocksize:
             with pytest.warns(UserWarning):
-                df = dd.read_csv("2014-01-*.csv", compression=fmt, blocksize=blocksize)
+                df = dd.read_csv("2014-01-*.csv" + suffix, blocksize=blocksize)
         else:
-            df = dd.read_csv("2014-01-*.csv", compression=fmt, blocksize=blocksize)
+            df = dd.read_csv("2014-01-*.csv" + suffix, blocksize=blocksize)
         assert_eq(
             df.compute(scheduler="sync").reset_index(drop=True),
             expected.reset_index(drop=True),

Add default compression="infer" option to read_csv
As discussed in [cudf#6850](https://github.com/rapidsai/cudf/issues/6850), `dask.dataframe`'s `read_csv` API does not match that of pandas when it comes to compression.  The default setting in pandas is `compression="infer"`, while dask uses `compression=None`.

@dask/io - Is there a strong argument against adding a default `"infer"` option to the dask API?

cc @lmeyerov

dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[zip-None] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[bz2-None] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[bz2-10] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[xz-10] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[gzip-None] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[xz-None] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[zip-10] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[gzip-10]
dask/dataframe/io/tests/test_csv.py::test_to_csv_warns_using_scheduler_argument dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_pandas_read_text_with_header[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_none_usecols dask/dataframe/io/tests/test_csv.py::test_read_csv_skiprows_only_in_first_partition[read_table-read_table-name\tamount\nAlice\t100\nBob\t-200\nCharlie\t300\nDennis\t400\nEdith\t-500\nFrank\t600\nAlice\t200\nFrank\t-200\nBob\t600\nAlice\t400\nFrank\t200\nAlice\t300\nEdith\t600-skip1] dask/dataframe/io/tests/test_csv.py::test_read_csv_slash_r dask/dataframe/io/tests/test_csv.py::test_to_single_csv_gzip dask/dataframe/io/tests/test_csv.py::test_to_csv_multiple_files_cornercases dask/dataframe/io/tests/test_csv.py::test_to_csv_header[False-False-a,1\n-d,4\n] dask/dataframe/io/tests/test_csv.py::test_read_csv_large_skiprows[read_csv-read_csv-name,amount\nAlice,100\nBob,-200\nCharlie,300\nDennis,400\nEdith,-500\nFrank,600\nAlice,200\nFrank,-200\nBob,600\nAlice,400\nFrank,200\nAlice,300\nEdith,600-7] dask/dataframe/io/tests/test_csv.py::test_auto_blocksize dask/dataframe/io/tests/test_csv.py::test_pandas_read_text[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_enforce_dtypes[read_csv-blocks0] dask/dataframe/io/tests/test_csv.py::test_robust_column_mismatch dask/dataframe/io/tests/test_csv.py::test_enforce_dtypes[read_table-blocks1] dask/dataframe/io/tests/test_csv.py::test_skiprows_as_list[read_csv-read_csv-files0-str, dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[None0-10] dask/dataframe/io/tests/test_csv.py::test_read_csv[read_table-read_table-name dask/dataframe/io/tests/test_csv.py::test_pandas_read_text_with_header[read_fwf-files2] dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column_as_str[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column_with_duplicate_name[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_to_csv dask/dataframe/io/tests/test_csv.py::test_empty_csv_file dask/dataframe/io/tests/test_csv.py::test_read_csv_files[read_csv-read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_to_csv_line_ending dask/dataframe/io/tests/test_csv.py::test_skiprows[read_table-read_table-files1] dask/dataframe/io/tests/test_csv.py::test_auto_blocksize_max64mb dask/dataframe/io/tests/test_csv.py::test_read_csv[read_csv-read_csv-name,amount\nAlice,100\nBob,-200\nCharlie,300\nDennis,400\nEdith,-500\nFrank,600\nAlice,200\nFrank,-200\nBob,600\nAlice,400\nFrank,200\nAlice,300\nEdith,600-,] dask/dataframe/io/tests/test_csv.py::test_pandas_read_text_dtype_coercion[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_to_csv_with_get dask/dataframe/io/tests/test_csv.py::test_text_blocks_to_pandas_simple[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_read_csv_files_list[read_table-read_table-files1] dask/dataframe/io/tests/test_csv.py::test_to_csv_header[True-True-x,y\n-d,4\n] dask/dataframe/io/tests/test_csv.py::test_enforce_columns[read_table-blocks1] dask/dataframe/io/tests/test_csv.py::test_to_csv_header[header4-False-aa,bb\n-aa,bb\n] dask/dataframe/io/tests/test_csv.py::test_error_if_sample_is_too_small dask/dataframe/io/tests/test_csv.py::test_read_csv_singleton_dtype dask/dataframe/io/tests/test_csv.py::test_to_csv_header_empty_dataframe[True-x,y\n] dask/dataframe/io/tests/test_csv.py::test_text_blocks_to_pandas_blocked[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_skiprows[read_csv-read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_windows_line_terminator dask/dataframe/io/tests/test_csv.py::test_text_blocks_to_pandas_blocked[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_read_csv_sensitive_to_enforce dask/dataframe/io/tests/test_csv.py::test_head_partial_line_fix dask/dataframe/io/tests/test_csv.py::test_read_csv_names_not_none dask/dataframe/io/tests/test_csv.py::test_to_csv_errors_using_multiple_scheduler_args dask/dataframe/io/tests/test_csv.py::test_string_blocksize dask/dataframe/io/tests/test_csv.py::test_categorical_dtypes dask/dataframe/io/tests/test_csv.py::test_auto_blocksize_csv dask/dataframe/io/tests/test_csv.py::test_categorical_known dask/dataframe/io/tests/test_csv.py::test_text_blocks_to_pandas_kwargs[read_fwf-files2] dask/dataframe/io/tests/test_csv.py::test_assume_missing dask/dataframe/io/tests/test_csv.py::test_to_csv_header[True-False-x,y\n-x,y\n] dask/dataframe/io/tests/test_csv.py::test_block_mask[block_lists1] dask/dataframe/io/tests/test_csv.py::test_to_csv_paths dask/dataframe/io/tests/test_csv.py::test_index_col dask/dataframe/io/tests/test_csv.py::test_to_csv_nodir dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column_as_str[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_pandas_read_text_dtype_coercion[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_pandas_read_text_kwargs[read_fwf-files2] dask/dataframe/io/tests/test_csv.py::test_text_blocks_to_pandas_blocked[read_fwf-files2] dask/dataframe/io/tests/test_csv.py::test_read_csv_sep dask/dataframe/io/tests/test_csv.py::test_text_blocks_to_pandas_kwargs[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_csv_with_integer_names dask/dataframe/io/tests/test_csv.py::test_read_csv_with_datetime_index_partitions_one dask/dataframe/io/tests/test_csv.py::test_block_mask[block_lists0] dask/dataframe/io/tests/test_csv.py::test_read_csv_has_different_names_based_on_blocksize dask/dataframe/io/tests/test_csv.py::test_read_csv_no_sample dask/dataframe/io/tests/test_csv.py::test_pandas_read_text[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_usecols dask/dataframe/io/tests/test_csv.py::test_read_csv_large_skiprows[read_table-read_table-name\tamount\nAlice\t100\nBob\t-200\nCharlie\t300\nDennis\t400\nEdith\t-500\nFrank\t600\nAlice\t200\nFrank\t-200\nBob\t600\nAlice\t400\nFrank\t200\nAlice\t300\nEdith\t600-skip1] dask/dataframe/io/tests/test_csv.py::test_reading_empty_csv_files_with_path dask/dataframe/io/tests/test_csv.py::test_text_blocks_to_pandas_simple[read_fwf-files2] dask/dataframe/io/tests/test_csv.py::test_to_csv_header_empty_dataframe[False-] dask/dataframe/io/tests/test_csv.py::test_read_csv_raises_on_no_files dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column_is_dtype_category[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_read_csv[read_table-read_table-name\tamount\nAlice\t100\nBob\t-200\nCharlie\t300\nDennis\t400\nEdith\t-500\nFrank\t600\nAlice\t200\nFrank\t-200\nBob\t600\nAlice\t400\nFrank\t200\nAlice\t300\nEdith\t600-\t] dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column_with_multiple_partitions_per_file[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_header_None dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column_with_duplicate_name[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_to_csv_simple dask/dataframe/io/tests/test_csv.py::test_read_csv_files[read_table-read_table-files1] dask/dataframe/io/tests/test_csv.py::test_parse_dates_multi_column dask/dataframe/io/tests/test_csv.py::test_skipinitialspace dask/dataframe/io/tests/test_csv.py::test_skiprows_as_list[read_table-read_table-files1-str\t dask/dataframe/io/tests/test_csv.py::test_multiple_read_csv_has_deterministic_name dask/dataframe/io/tests/test_csv.py::test_to_single_csv_with_name_function dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[None1-10] dask/dataframe/io/tests/test_csv.py::test_read_csv_has_deterministic_name dask/dataframe/io/tests/test_csv.py::test_pandas_read_text_kwargs[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_to_csv_header[header5-True-aa,bb\n-d,4\n] dask/dataframe/io/tests/test_csv.py::test_read_csv_header_issue_823 dask/dataframe/io/tests/test_csv.py::test_to_single_csv_with_header_first_partition_only dask/dataframe/io/tests/test_csv.py::test_block_mask[block_lists2] dask/dataframe/io/tests/test_csv.py::test_encoding_gh601[utf-16-be] dask/dataframe/io/tests/test_csv.py::test_pandas_read_text_with_header[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_read_csv_files_list[read_csv-read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_block_mask[block_lists3] dask/dataframe/io/tests/test_csv.py::test_to_csv_series dask/dataframe/io/tests/test_csv.py::test_pandas_read_text_dtype_coercion[read_fwf-files2] dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column_is_dtype_category[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[None1-None] dask/dataframe/io/tests/test_csv.py::test_pandas_read_text_kwargs[read_csv-files0] dask/dataframe/io/tests/test_csv.py::test_text_blocks_to_pandas_kwargs[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_late_dtypes dask/dataframe/io/tests/test_csv.py::test_to_single_csv dask/dataframe/io/tests/test_csv.py::test_read_csv_skiprows_only_in_first_partition[read_csv-read_csv-name,amount\nAlice,100\nBob,-200\nCharlie,300\nDennis,400\nEdith,-500\nFrank,600\nAlice,200\nFrank,-200\nBob,600\nAlice,400\nFrank,200\nAlice,300\nEdith,600-7] dask/dataframe/io/tests/test_csv.py::test_read_csv_compression[None0-None] dask/dataframe/io/tests/test_csv.py::test_read_csv_skiprows_range dask/dataframe/io/tests/test_csv.py::test_consistent_dtypes_2 dask/dataframe/io/tests/test_csv.py::test_read_csv_include_path_column_with_multiple_partitions_per_file[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_to_csv_keeps_all_non_scheduler_compute_kwargs dask/dataframe/io/tests/test_csv.py::test_text_blocks_to_pandas_simple[read_table-files1] dask/dataframe/io/tests/test_csv.py::test_pandas_read_text[read_fwf-files2] dask/dataframe/io/tests/test_csv.py::test_to_csv_header[False-True-a,1\n-d,4\n] dask/dataframe/io/tests/test_csv.py::test_consistent_dtypes dask/dataframe/io/tests/test_csv.py::test_enforce_columns[read_csv-blocks0]