Repository: tailwindlabs/tailwindcss

Problem statement:
Add break-all utility, change word-wrap to overflow-wrap
👋 

Fix #411 

This PR:

- Adds a `.break-all` class
- Changes `word-wrap` to `overflow-wrap` (https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap)

Thanks!


Hints:
Docs updated in [#47.](https://github.com/tailwindcss/docs/pull/47)
Thanks for this! I really want to merge it but there's an annoying decision we have to figure out...

Right now you can use `break-normal` to "undo" `break-words` at various breakpoints, like:

```
<div class="break-words md:break-normal">...</div>
```

...but because `break-all` has to use the `word-break` property, there's currently no way to undo it since `break-normal` uses `overflow-wrap`.

I see two solutions:

1. **Make `break-normal` do two things**

    If `break-normal` were defined like this it would fix the problem:

    ```
    .break-normal {
        overflow-wrap: normal;
        word-break: normal;
    }
    ```

    I'm not sure if there are actually cases where you *wouldn't* want this to happen though, like maybe you want `overflow-wrap: normal` and `word-break: break-all` or some other combination. It's also very rare that any of Tailwind's utilities set multiple properties, I think `truncate` is the only other one and we have talked in the past about "fixing" that 😕

2. **Add another class**

    We could add a new class specifically for `word-break: normal` but what the hell would we call it?

    I think if we did that we'd probably need to rename the `overflow-wrap` utilities, or at least `break-normal` to `wrap-normal`, so `word-break: normal` could be called `break-normal`. This sucks because it's a breaking change.

Any ideas or thoughts? 🤔 
Thanks for your feedback!

I see the problem, not an easy nut to crack. Been doing some thinking and this is my take on all this:

1.  **Make `break-normal` do two things**

    Instead of making `.break-normal` do two things we could introduce a `.break-reset` class similar to `.list-reset` but for word-wrapping in general:

    ```
    .break-reset {
        overflow-wrap: normal;
        word-break: normal;
    }
    ```

    This way we could keep the current class names as is, hence not introducing a breaking change.

    Then again as you said, if this kind of utility classes are going to be fixed/removed in future releases then maybe it's a bad idea to add yet another one. 

    I'm also, like you - not sure if there are actually cases where you _wouldn't_ want this to happen, maybe there has to be a seperate class for resetting `word-break: break-all` specifically. I'm not sure..

2. **Add another class**

    It does indeed suck that changing the names would be a breaking change, however it wouldn't make sense (at least not to me) to have `overflow-wrap: normal` being named `.break-normal` if `word-break: normal` was introduced to the framework. I feel a change of the class names in this scenario is a must:

    ```
    'wrap-words': { 'overflow-wrap': 'break-word' },
    'wrap-normal': { 'overflow-wrap': 'normal' },
    'break-normal': { 'word-break': 'normal' },
    'break-all': { 'word-break': 'break-all' },
    ```

**Conclusion**

I'm really not sure what's the best option here, or if there is another better way of doing this. At least I haven't come up with anything else so far other than my suggestion about adding a `.break-reset` class which is basically what you already suggested. In the meantime, I'll keep thinking about this to see if I can come up with something better. 🤔 
Coming back to this since we can break this for 1.0, I think I'm okay with these names...

```
'wrap-break': { 'overflow-wrap': 'break-word' },
'wrap-normal': { 'overflow-wrap': 'normal' },
'break-normal': { 'word-break': 'normal' },
'break-all': { 'word-break': 'break-all' },
```

Anyone have any thoughts? I don't like `wrap-words` because words already wrap by default, so doesn't really feel like it describes it properly. `wrap-break` is kind of awkward too but it feels a bit closer.

Still considering just making `break-normal` unset both properties, I think I would be fine with that if no one can think of a scenario (no matter how obscure) where that would be problematic.
@adamwathan sounds good to me!

Patch:
diff --git a/src/plugins/whitespace.js b/src/plugins/whitespace.js
--- a/src/plugins/whitespace.js
+++ b/src/plugins/whitespace.js
@@ -8,8 +8,11 @@ export default function({ variants }) {
         '.whitespace-pre-line': { 'white-space': 'pre-line' },
         '.whitespace-pre-wrap': { 'white-space': 'pre-wrap' },
 
-        '.break-words': { 'word-wrap': 'break-word' },
-        '.break-normal': { 'word-wrap': 'normal' },
+        '.wrap-break': { 'overflow-wrap': 'break-word' },
+        '.wrap-normal': { 'overflow-wrap': 'normal' },
+
+        '.break-normal': { 'word-break': 'normal' },
+        '.break-all': { 'word-break': 'break-all' },
 
         '.truncate': {
           overflow: 'hidden',


Test patch:
diff --git a/__tests__/fixtures/tailwind-output-important.css b/__tests__/fixtures/tailwind-output-important.css
--- a/__tests__/fixtures/tailwind-output-important.css
+++ b/__tests__/fixtures/tailwind-output-important.css
@@ -6019,12 +6019,20 @@ table {
   white-space: pre-wrap !important;
 }
 
-.break-words {
-  word-wrap: break-word !important;
+.wrap-break {
+  overflow-wrap: break-word !important;
+}
+
+.wrap-normal {
+  overflow-wrap: normal !important;
 }
 
 .break-normal {
-  word-wrap: normal !important;
+  word-break: normal !important;
+}
+
+.break-all {
+  word-break: break-all !important;
 }
 
 .truncate {
@@ -11680,12 +11688,20 @@ table {
     white-space: pre-wrap !important;
   }
 
-  .sm\:break-words {
-    word-wrap: break-word !important;
+  .sm\:wrap-break {
+    overflow-wrap: break-word !important;
+  }
+
+  .sm\:wrap-normal {
+    overflow-wrap: normal !important;
   }
 
   .sm\:break-normal {
-    word-wrap: normal !important;
+    word-break: normal !important;
+  }
+
+  .sm\:break-all {
+    word-break: break-all !important;
   }
 
   .sm\:truncate {
@@ -17342,12 +17358,20 @@ table {
     white-space: pre-wrap !important;
   }
 
-  .md\:break-words {
-    word-wrap: break-word !important;
+  .md\:wrap-break {
+    overflow-wrap: break-word !important;
+  }
+
+  .md\:wrap-normal {
+    overflow-wrap: normal !important;
   }
 
   .md\:break-normal {
-    word-wrap: normal !important;
+    word-break: normal !important;
+  }
+
+  .md\:break-all {
+    word-break: break-all !important;
   }
 
   .md\:truncate {
@@ -23004,12 +23028,20 @@ table {
     white-space: pre-wrap !important;
   }
 
-  .lg\:break-words {
-    word-wrap: break-word !important;
+  .lg\:wrap-break {
+    overflow-wrap: break-word !important;
+  }
+
+  .lg\:wrap-normal {
+    overflow-wrap: normal !important;
   }
 
   .lg\:break-normal {
-    word-wrap: normal !important;
+    word-break: normal !important;
+  }
+
+  .lg\:break-all {
+    word-break: break-all !important;
   }
 
   .lg\:truncate {
@@ -28666,12 +28698,20 @@ table {
     white-space: pre-wrap !important;
   }
 
-  .xl\:break-words {
-    word-wrap: break-word !important;
+  .xl\:wrap-break {
+    overflow-wrap: break-word !important;
+  }
+
+  .xl\:wrap-normal {
+    overflow-wrap: normal !important;
   }
 
   .xl\:break-normal {
-    word-wrap: normal !important;
+    word-break: normal !important;
+  }
+
+  .xl\:break-all {
+    word-break: break-all !important;
   }
 
   .xl\:truncate {
diff --git a/__tests__/fixtures/tailwind-output.css b/__tests__/fixtures/tailwind-output.css
--- a/__tests__/fixtures/tailwind-output.css
+++ b/__tests__/fixtures/tailwind-output.css
@@ -6019,12 +6019,20 @@ table {
   white-space: pre-wrap;
 }
 
-.break-words {
-  word-wrap: break-word;
+.wrap-break {
+  overflow-wrap: break-word;
+}
+
+.wrap-normal {
+  overflow-wrap: normal;
 }
 
 .break-normal {
-  word-wrap: normal;
+  word-break: normal;
+}
+
+.break-all {
+  word-break: break-all;
 }
 
 .truncate {
@@ -11680,12 +11688,20 @@ table {
     white-space: pre-wrap;
   }
 
-  .sm\:break-words {
-    word-wrap: break-word;
+  .sm\:wrap-break {
+    overflow-wrap: break-word;
+  }
+
+  .sm\:wrap-normal {
+    overflow-wrap: normal;
   }
 
   .sm\:break-normal {
-    word-wrap: normal;
+    word-break: normal;
+  }
+
+  .sm\:break-all {
+    word-break: break-all;
   }
 
   .sm\:truncate {
@@ -17342,12 +17358,20 @@ table {
     white-space: pre-wrap;
   }
 
-  .md\:break-words {
-    word-wrap: break-word;
+  .md\:wrap-break {
+    overflow-wrap: break-word;
+  }
+
+  .md\:wrap-normal {
+    overflow-wrap: normal;
   }
 
   .md\:break-normal {
-    word-wrap: normal;
+    word-break: normal;
+  }
+
+  .md\:break-all {
+    word-break: break-all;
   }
 
   .md\:truncate {
@@ -23004,12 +23028,20 @@ table {
     white-space: pre-wrap;
   }
 
-  .lg\:break-words {
-    word-wrap: break-word;
+  .lg\:wrap-break {
+    overflow-wrap: break-word;
+  }
+
+  .lg\:wrap-normal {
+    overflow-wrap: normal;
   }
 
   .lg\:break-normal {
-    word-wrap: normal;
+    word-break: normal;
+  }
+
+  .lg\:break-all {
+    word-break: break-all;
   }
 
   .lg\:truncate {
@@ -28666,12 +28698,20 @@ table {
     white-space: pre-wrap;
   }
 
-  .xl\:break-words {
-    word-wrap: break-word;
+  .xl\:wrap-break {
+    overflow-wrap: break-word;
+  }
+
+  .xl\:wrap-normal {
+    overflow-wrap: normal;
   }
 
   .xl\:break-normal {
-    word-wrap: normal;
+    word-break: normal;
+  }
+
+  .xl\:break-all {
+    word-break: break-all;
   }
 
   .xl\:truncate {