diff --git a/core/modules/views/src/Plugin/views/area/TokenizeAreaPluginBase.php b/core/modules/views/src/Plugin/views/area/TokenizeAreaPluginBase.php
index bf6fbf6..d29fa1a 100644
--- a/core/modules/views/src/Plugin/views/area/TokenizeAreaPluginBase.php
+++ b/core/modules/views/src/Plugin/views/area/TokenizeAreaPluginBase.php
@@ -106,10 +106,8 @@ public function tokenForm(&$form, FormStateInterface $form_state) {
    */
   public function tokenizeValue($value) {
     if ($this->options['tokenize']) {
-      $value = $this->view->style_plugin->tokenizeValue($value, 0);
+      $value = $this->view->getStyle()->tokenizeValue($value, 0);
     }
     // As we add the globalTokenForm() we also should replace the token here.
     return $this->globalTokenReplace($value);
   }
-
-}
diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
index 4459ac2..fab7664 100644
--- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
+++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
@@ -337,7 +337,7 @@ public function elementClasses($row_index = NULL) {
    * tokens so they will all be available.
    */
   public function tokenizeValue($value, $row_index = NULL) {
-    if (strpos($value, '[') !== FALSE || strpos($value, '!') !== FALSE || strpos($value, '%') !== FALSE) {
+    if ($this->view->getStyle()->hasRowToken($value) || $this->view->getStyle()->hasArgToken($value)) {
       $fake_item = array(
         'alter_text' => TRUE,
         'text' => $value,
diff --git a/core/modules/views/src/Plugin/views/style/StylePluginBase.php b/core/modules/views/src/Plugin/views/style/StylePluginBase.php
index aa2d8e8..5bfc0d1 100644
--- a/core/modules/views/src/Plugin/views/style/StylePluginBase.php
+++ b/core/modules/views/src/Plugin/views/style/StylePluginBase.php
@@ -184,20 +184,6 @@ function usesFields() {
   }
 
   /**
-   * Return TRUE if this style uses tokens.
-   *
-   * Used to ensure we don't fetch tokens when not needed for performance.
-   */
-  public function usesTokens() {
-    if ($this->usesRowClass()) {
-      $class = $this->options['row_class'];
-      if (strpos($class, '[') !== FALSE || strpos($class, '!') !== FALSE || strpos($class, '%') !== FALSE) {
-        return TRUE;
-      }
-    }
-  }
-
-  /**
    * Return TRUE if this style enables field labels by default.
    *
    * @return bool
@@ -228,7 +214,7 @@ public function getRowClass($row_index) {
    * Take a value and apply token replacement logic to it.
    */
   public function tokenizeValue($value, $row_index) {
-    if (strpos($value, '[') !== FALSE || strpos($value, '!') !== FALSE || strpos($value, '%') !== FALSE) {
+    if ($this->hasArgToken($value) || $this->hasRowToken($value)) {
       // Row tokens might be empty, for example for node row style.
       $tokens = isset($this->rowTokens[$row_index]) ? $this->rowTokens[$row_index] : array();
       if (!empty($this->view->build_info['substitutions'])) {
@@ -244,6 +230,81 @@ public function tokenizeValue($value, $row_index) {
   }
 
   /**
+   * Indicates whether the value has a Views argument token.
+   *
+   * @param string $value
+   *   The string to check
+   *
+   * @return bool
+   *   TRUE if the string has a Views token.
+   */
+  public function hasArgToken($value) {
+    // If the string definitely does not contain a token, return FALSE
+    // immediately for performance.
+    if ((strpos($value, '!') === FALSE) && (strpos($value, '%') === FALSE)) {
+      return FALSE;
+    }
+    // Otherwise, scan for valid token patterns.
+    return (preg_match('/[!%]\d*/', $value) !== FALSE);
+  }
+
+  /**
+   * Indicates whether the value has a Views row-level token.
+   *
+   * @param string $value
+   *   The string to check
+   *
+   * @return bool
+   *   TRUE if the string has a global token.
+   */
+  public function hasRowToken($value) {
+    // If the string definitely does not contain a token, return FALSE
+    // immediately for performance.
+    if (strpos($value, '[') === FALSE) {
+      return FALSE;
+    }
+    // Otherwise, scan for valid token patterns.
+    $tokens = \Drupal::token()->scan($value);
+    // Match any non-empty string between [ and ] that does not contain [ or ].
+    return (preg_match('/\[[^\[\]]+\]/', $value) !== FALSE);
+  }
+
+  /**
+   * Indicates whether the value has a global token.
+   *
+   * @param string $value
+   *   The string to check
+   *
+   * @return bool
+   *   TRUE if the string has a global token.
+   *
+   * @see \Drupal\Core\Utility\Token
+   */
+  public function hasGlobalToken($value) {
+    // If the string definitely does not contain a token, return FALSE
+    // immediately for performance.
+    if (strpos($value, '[') === FALSE) {
+      return FALSE;
+    }
+    // Otherwise, scan for valid token patterns.
+    $tokens = \Drupal::token()->scan($value);
+    return (!empty($tokens));
+  }
+
+  /**
+   * Indicates whether the value has a special Views token or a global token.
+   *
+   * @param string $value
+   *   The string to check
+   *
+   * @return bool
+   *   TRUE if the string has any token.
+   */
+  public function hasToken($value) {
+    return ($this->hasArgToken($value) || $this->hasRowToken($value) || $this->hasGlobalToken($value));
+  }
+
+  /**
    * Should the output of the style plugin be rendered even if it's a empty view.
    */
   public function evenEmpty() {
