diff --git a/crop.module b/crop.module
index 0aad0d1..30469f8 100644
--- a/crop.module
+++ b/crop.module
@@ -8,6 +8,9 @@
  */
 
 use \Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StreamWrapper\PublicStream;
+use Drupal\crop\Entity\Crop;
+use Drupal\image\Entity\ImageStyle;
 use \Drupal\media_entity\MediaBundleInterface;
 use \Drupal\file\FileInterface;
 
@@ -108,3 +111,37 @@ function crop_file_delete(FileInterface $file) {
     $crop->delete();
   }
 }
+
+/**
+ * Implements hook_file_url_alter().
+ */
+function crop_file_url_alter(&$uri) {
+  // Parse given URI.
+  $uri_info = parse_url($uri);
+  // Use schema information to skip relative URIs.
+  $protocol = isset($uri_info['scheme']) ? in_array($uri_info['scheme'], ['http', 'https']) : FALSE;
+
+  // Process only files that are stored in "styles" directory.
+  if ($protocol && strpos($uri, PublicStream::basePath() . '/styles/') !== FALSE) {
+    // Match image style, schema, file subdirectory and file name.
+    preg_match("/styles\/(.*?)\/(.*?)\/(.*?)\?/", $uri, $match);
+    // Get the image style ID.
+    $image_style = $match[1];
+    // Get the file URI using parsed schema and file path.
+    $file_uri = $match[2] . '://' . $match[3];
+
+    /** @var \Drupal\image_widget_crop\ImageWidgetCropManager $image_widget_manager */
+    $image_widget_manager = \Drupal::service('image_widget_crop.manager');
+
+    /** @var \Drupal\image\Entity\ImageStyle $image_style */
+    $image_style = ImageStyle::load($image_style);
+
+    // In case the image style uses "crop_type" effect, load the crop entity.
+    if ($crop = Crop::findCrop($file_uri, $image_widget_manager->getEffectData($image_style, 'crop_type'))) {
+      // Appending updated crop position and anchor values to the file URI will
+      // tell browser to create a new request to the image.
+      $query_string = implode($crop->position(), '-') . '-' . implode($crop->anchor(), '-');
+      $uri .= '&v=' . $query_string;
+    }
+  }
+}
