diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md
index 1218fe9..dcdd656 100644
--- a/docs/src/markdown/about/changelog.md
+++ b/docs/src/markdown/about/changelog.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 1.2.2
+
+- **FIX**: Fix `[attr~=value]` handling of whitespace. According to the spec, if the value contains whitespace, or is an empty string, it should not match anything.
+
 ## 1.2.1
 
 - **FIX**: More descriptive exceptions. Exceptions will also now mention position in the pattern that is problematic.
diff --git a/soupsieve/__meta__.py b/soupsieve/__meta__.py
index 209f355..c414e70 100644
--- a/soupsieve/__meta__.py
+++ b/soupsieve/__meta__.py
@@ -186,5 +186,5 @@ def parse_version(ver, pre=False):
     return Version(major, minor, micro, release, pre, post, dev)
 
 
-__version_info__ = Version(1, 2, 1, "final")
+__version_info__ = Version(1, 2, 2, ".dev")
 __version__ = __version_info__._get_canonical()
diff --git a/soupsieve/css_parser.py b/soupsieve/css_parser.py
index 355bfec..dfe796d 100644
--- a/soupsieve/css_parser.py
+++ b/soupsieve/css_parser.py
@@ -132,6 +132,8 @@ RE_NTH = re.compile(r'(?P<s1>[-+])?(?P<a>\d+n?|n)(?:(?<=n){ws}*(?P<s2>[-+]){ws}*
 
 RE_LANG = re.compile(r'(?:(?P<value>{value})|(?P<split>{ws}*,{ws}*))'.format(ws=WS, value=VALUE), re.X)
 
+RE_WS = re.compile(WS)
+
 SPLIT = ','
 REL_HAS_CHILD = ": "
 
@@ -345,7 +347,10 @@ class CSSParser(object):
                 pattern = re.compile(r'.*?%s.*' % re.escape(value), flags)
             elif op.startswith('~'):
                 # Value contains word within space separated list
-                pattern = re.compile(r'.*?(?:(?<=^)|(?<= ))%s(?=(?:[ ]|$)).*' % re.escape(value), flags)
+                # `~=` should match nothing if it is empty or contains whitespace,
+                # so if either of these cases is present, use `[^\s\S]` which cannot be matched.
+                value = r'[^\s\S]' if not value or RE_WS.search(value) else re.escape(value)
+                pattern = re.compile(r'.*?(?:(?<=^)|(?<= ))%s(?=(?:[ ]|$)).*' % value, flags)
             elif op.startswith('|'):
                 # Value starts with word in dash separated list
                 pattern = re.compile(r'^%s(?:-.*)?$' % re.escape(value), flags)

[attr~=value] spec issue
According to the spec

> [att~=val]
Represents an element with the att attribute whose value is a whitespace-separated list of words, one of which is exactly "val". If "val" contains whitespace, it will never represent anything (since the words are separated by spaces). Also if "val" is the empty string, it will never represent anything.

We are currently not enforcing this, but we should (the whitespace part).
diff --git a/tests/test_level2.py b/tests/test_level2.py
index c9bf1ed..033f5f0 100644
--- a/tests/test_level2.py
+++ b/tests/test_level2.py
@@ -328,6 +328,26 @@ class TestLevel2(util.TestCase):
             flags=util.HTML5
         )
 
+        # Shouldn't match anything
+        self.assert_selector(
+            markup,
+            '[class~="test1 test2"]',
+            [],
+            flags=util.HTML5
+        )
+        self.assert_selector(
+            markup,
+            '[class~=""]',
+            [],
+            flags=util.HTML5
+        )
+        self.assert_selector(
+            markup,
+            '[class~="test1\\ test2"]',
+            [],
+            flags=util.HTML5
+        )
+
         # Start of list
         self.assert_selector(
             markup,

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov coverage lxml beautifulsoup4
apt-get update apt-get install -y gcc
3.9
requirements/project.txt requirements/tests.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
beautifulsoup4==4.13.3
coverage==7.8.0
exceptiongroup==1.2.2
html5lib==1.1
iniconfig==2.1.0
lxml==5.3.1
packaging==24.2
pluggy==1.5.0
pytest==8.3.5
pytest-cov==6.0.0
six==1.17.0
-e git+https://github.com/facelessuser/soupsieve.git@96dc075c960edd14ddc372ed492fd9b08296b39d#egg=soupsieve
tomli==2.2.1
typing_extensions==4.13.0
webencodings==0.5.1

name: soupsieve
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - beautifulsoup4==4.13.3
      - coverage==7.8.0
      - exceptiongroup==1.2.2
      - html5lib==1.1
      - iniconfig==2.1.0
      - lxml==5.3.1
      - packaging==24.2
      - pluggy==1.5.0
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - six==1.17.0
      - tomli==2.2.1
      - typing-extensions==4.13.0
      - webencodings==0.5.1
prefix: /opt/conda/envs/soupsieve

tests/test_level2.py::TestLevel2::test_attribute_contains_space
tests/test_level2.py::TestLevel2::test_attribute tests/test_level2.py::TestLevel2::test_attribute_equal tests/test_level2.py::TestLevel2::test_attribute_start_dash tests/test_level2.py::TestLevel2::test_attribute_type tests/test_level2.py::TestLevel2::test_direct_child tests/test_level2.py::TestLevel2::test_direct_sibling tests/test_level2.py::TestLevel2::test_first_child tests/test_level2.py::TestLevel2::test_focus tests/test_level2.py::TestLevel2::test_hover tests/test_level2.py::TestLevel2::test_lang tests/test_level2.py::TestLevel2::test_multi_attribute tests/test_level2.py::TestLevel2::test_pseudo_element tests/test_level2.py::TestLevel2::test_wild_tag
soupsieve/__meta__.py docs/src/markdown/about/changelog.md soupsieve/css_parser.py
soupsieve/__meta__.py docs/src/markdown/about/changelog.md soupsieve/css_parser.py