diff --git a/assets/images/loading.svg b/assets/images/loading.svg
new file mode 100644
index 00000000..02a0eee4
--- /dev/null
+++ b/assets/images/loading.svg
@@ -0,0 +1,5 @@
+
diff --git a/layouts/partials/plugin/image.html b/layouts/partials/plugin/image.html
new file mode 100644
index 00000000..3d6ae5a7
--- /dev/null
+++ b/layouts/partials/plugin/image.html
@@ -0,0 +1,40 @@
+{{- $params := page.Scratch.Get "params" -}}
+{{- $class := .Class | default "" -}}
+{{- $style := "" -}}
+{{- $loading := .Loading | default "lazy" -}}
+{{- $onload := "" -}}
+{{- $onerror := "" -}}
+{{- $cacheRemoteImages := $params.cacheRemoteImages -}}
+{{- $suffixList := slice ".jpeg" ".jpg" ".png" ".gif" ".bmp" ".tif" ".tiff" ".webp" -}}
+
+{{- /* handle for image size */ -}}
+{{- $src := .Src -}}
+{{- $srcSmall := .SrcSmall | default $src -}}
+{{- $srcMedium := $src -}}
+{{- $srcLarge := .SrcLarge | default $src -}}
+
+
+{{- /* set image alt */ -}}
+{{- $alt := .Alt | default $src -}}
+
+{{- /* set image lazy loading */ -}}
+{{- if eq $loading "lazy" -}}
+ {{- $commonScript := "this.title=this.dataset.title;for(const i of ['style', 'data-title','onerror','onload']){this.removeAttribute(i);}" -}}
+ {{- $onload = printf " onload=\"%vthis.dataset.lazyloaded='';\"" $commonScript | safeHTMLAttr -}}
+ {{- $onerror = printf " onerror=\"%v\"" $commonScript | safeHTMLAttr -}}
+ {{- $style = printf " style=\"%vbackground: url(%v) no-repeat center;\"" $style (resources.Get "/images/loading.svg" | minify).RelPermalink | safeHTMLAttr -}}
+{{- end -}}
+
+
diff --git a/layouts/shortcodes/image.html b/layouts/shortcodes/image.html
new file mode 100644
index 00000000..2d45484b
--- /dev/null
+++ b/layouts/shortcodes/image.html
@@ -0,0 +1,15 @@
+{{- $options := cond .IsNamedParams (.Get "src") (.Get 0) | dict "Src" -}}
+{{- $options = cond .IsNamedParams (.Get "alt") (.Get 1) | .Page.RenderString | dict "Alt" | merge $options -}}
+
+{{- if .IsNamedParams -}}
+ {{- $options = dict "Title" (.Get "title") | merge $options -}}
+ {{- $options = dict "SrcSmall" (.Get "src_s") | merge $options -}}
+ {{- $options = dict "SrcLarge" (.Get "src_l") | merge $options -}}
+ {{- $options = dict "Height" (.Get "height") | merge $options -}}
+ {{- $options = dict "Width" (.Get "width") | merge $options -}}
+ {{- $options = .Get "linked" | ne false | dict "Linked" | merge $options -}}
+ {{- $options = dict "Rel" (.Get "rel") | merge $options -}}
+ {{- $options = dict "Loading" (.Get "loading") | merge $options -}}
+ {{- $options = dict "Responsive" true | merge $options -}}
+ {{- partial "plugin/image.html" $options -}}
+{{- end -}}
\ No newline at end of file