Resize Images Dynamically
I set out to make a simple dynamic resize method for images. Obviously, it's better to serve images that are pre-sized to avoid unnecessary server loads. But it was fun to make for a novice/beginner jQuery project and not really meant for a production project. For many of you, I'm sure it'll be rudimentary at best, but that's why I'm posting it here, to get some advice on ways to improve it.
The goal,
- Add wrappers dynamically (wrapInner for content structure inside .topic), add wrapper around images to constrain the content image sizes.
- dynamic width & height attributes on images - onLoad & onResize
- Dynamic query string on img.src (URL adds ?width=###&height=###)
onLoad & resize (for demo purposes I'm using "placehold.it/###x###") this is
only needed for content images in the DOM. - Real width & height of image set to parent (figure) as max-width/height
onLoad - Debounce/throttle resize events to avoid excess events begin fired. (used a method displayed on css-tricks.com and can be found here)
The CSS and HTML is more to make the demo look nice but if you have some input for that as well, by all means. Like I said, I'm certainly not a jQuery developer, though I'm trying to learn as quickly as possible to augment my skill set. So if you have any advice or input on areas that can improve, I'd greatly appreciate it.
Fiddle: DEMO
$(function() {
// demo fun
$('.topic').each(function() {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')) {
$('.media-support:odd').addClass('inverse');
}
});
});
var sizeTimer;
$(window).on('load', function() {
var img = new Image();
$('img').each(function() {
var $this = $(this),
image = new Image(),
_imgWidth = $(this).width(),
_imgHeight = $(this).height(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
$this.attr({
'width': +_imgWidth,
'height': +_imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
}).wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function() {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function() {
$('img').each(function() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width': _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
});
}, 250);
});
javascript beginner jquery image event-handling
add a comment |
I set out to make a simple dynamic resize method for images. Obviously, it's better to serve images that are pre-sized to avoid unnecessary server loads. But it was fun to make for a novice/beginner jQuery project and not really meant for a production project. For many of you, I'm sure it'll be rudimentary at best, but that's why I'm posting it here, to get some advice on ways to improve it.
The goal,
- Add wrappers dynamically (wrapInner for content structure inside .topic), add wrapper around images to constrain the content image sizes.
- dynamic width & height attributes on images - onLoad & onResize
- Dynamic query string on img.src (URL adds ?width=###&height=###)
onLoad & resize (for demo purposes I'm using "placehold.it/###x###") this is
only needed for content images in the DOM. - Real width & height of image set to parent (figure) as max-width/height
onLoad - Debounce/throttle resize events to avoid excess events begin fired. (used a method displayed on css-tricks.com and can be found here)
The CSS and HTML is more to make the demo look nice but if you have some input for that as well, by all means. Like I said, I'm certainly not a jQuery developer, though I'm trying to learn as quickly as possible to augment my skill set. So if you have any advice or input on areas that can improve, I'd greatly appreciate it.
Fiddle: DEMO
$(function() {
// demo fun
$('.topic').each(function() {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')) {
$('.media-support:odd').addClass('inverse');
}
});
});
var sizeTimer;
$(window).on('load', function() {
var img = new Image();
$('img').each(function() {
var $this = $(this),
image = new Image(),
_imgWidth = $(this).width(),
_imgHeight = $(this).height(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
$this.attr({
'width': +_imgWidth,
'height': +_imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
}).wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function() {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function() {
$('img').each(function() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width': _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
});
}, 250);
});
javascript beginner jquery image event-handling
add a comment |
I set out to make a simple dynamic resize method for images. Obviously, it's better to serve images that are pre-sized to avoid unnecessary server loads. But it was fun to make for a novice/beginner jQuery project and not really meant for a production project. For many of you, I'm sure it'll be rudimentary at best, but that's why I'm posting it here, to get some advice on ways to improve it.
The goal,
- Add wrappers dynamically (wrapInner for content structure inside .topic), add wrapper around images to constrain the content image sizes.
- dynamic width & height attributes on images - onLoad & onResize
- Dynamic query string on img.src (URL adds ?width=###&height=###)
onLoad & resize (for demo purposes I'm using "placehold.it/###x###") this is
only needed for content images in the DOM. - Real width & height of image set to parent (figure) as max-width/height
onLoad - Debounce/throttle resize events to avoid excess events begin fired. (used a method displayed on css-tricks.com and can be found here)
The CSS and HTML is more to make the demo look nice but if you have some input for that as well, by all means. Like I said, I'm certainly not a jQuery developer, though I'm trying to learn as quickly as possible to augment my skill set. So if you have any advice or input on areas that can improve, I'd greatly appreciate it.
Fiddle: DEMO
$(function() {
// demo fun
$('.topic').each(function() {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')) {
$('.media-support:odd').addClass('inverse');
}
});
});
var sizeTimer;
$(window).on('load', function() {
var img = new Image();
$('img').each(function() {
var $this = $(this),
image = new Image(),
_imgWidth = $(this).width(),
_imgHeight = $(this).height(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
$this.attr({
'width': +_imgWidth,
'height': +_imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
}).wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function() {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function() {
$('img').each(function() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width': _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
});
}, 250);
});
javascript beginner jquery image event-handling
I set out to make a simple dynamic resize method for images. Obviously, it's better to serve images that are pre-sized to avoid unnecessary server loads. But it was fun to make for a novice/beginner jQuery project and not really meant for a production project. For many of you, I'm sure it'll be rudimentary at best, but that's why I'm posting it here, to get some advice on ways to improve it.
The goal,
- Add wrappers dynamically (wrapInner for content structure inside .topic), add wrapper around images to constrain the content image sizes.
- dynamic width & height attributes on images - onLoad & onResize
- Dynamic query string on img.src (URL adds ?width=###&height=###)
onLoad & resize (for demo purposes I'm using "placehold.it/###x###") this is
only needed for content images in the DOM. - Real width & height of image set to parent (figure) as max-width/height
onLoad - Debounce/throttle resize events to avoid excess events begin fired. (used a method displayed on css-tricks.com and can be found here)
The CSS and HTML is more to make the demo look nice but if you have some input for that as well, by all means. Like I said, I'm certainly not a jQuery developer, though I'm trying to learn as quickly as possible to augment my skill set. So if you have any advice or input on areas that can improve, I'd greatly appreciate it.
Fiddle: DEMO
$(function() {
// demo fun
$('.topic').each(function() {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')) {
$('.media-support:odd').addClass('inverse');
}
});
});
var sizeTimer;
$(window).on('load', function() {
var img = new Image();
$('img').each(function() {
var $this = $(this),
image = new Image(),
_imgWidth = $(this).width(),
_imgHeight = $(this).height(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
$this.attr({
'width': +_imgWidth,
'height': +_imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
}).wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function() {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function() {
$('img').each(function() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width': _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
});
}, 250);
});
javascript beginner jquery image event-handling
javascript beginner jquery image event-handling
edited 31 mins ago
Sᴀᴍ Onᴇᴌᴀ
8,29861853
8,29861853
asked Nov 19 '15 at 17:17
darcher
459215
459215
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
I know that this code was posted more than three years ago and you have likely learned many things since then but I'd rather not see it be a zombie any longer... so here we go:
In general the code looks okay. There aren't too many repeated blocks. There are a few suggestions I have to tidy up the code.
Cache DOM references - instead of querying for collections like
$('img')multiple times, do that once the DOM is loaded, store the collection in a variable and then reference the variable instead of re-querying.
var images
$(window).load(function() {
images = $('img');
images.each(function () {
and later in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(function () {
unused variable:
imgthis variable doesn't appear to be used anywhere after it is created:var img = new Image();. Perhaps that is left from a side venture in the code...
Don't repeat code this may only be achievable with advanced function manipulation so I wouldn't expect you to do this in one of your first projects but the code that exists in the callback function on the resize event executed for each image could be abstracted out to a separate function:
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
Then that function can be used in the load callback, utilizing
Function.prototype.apply():
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
This means
_imgWidthand_imgHeightdon't have to be declared again in the load handler, since the call tosetAttributesOnImage()handles that.
And also in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(setAttributesOnImage)
}, 250);
Also, that last timeout callback could be simplified, using
Function.prototype.bind()to create a Partially applied function:
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
Snippet
Expand the snippet below to see simplified code.
/* Goal:
1. add wrapper around .topic contents (wrapInner) onDocReady
2. add wrapper around images (wrap) onDocReady
3. dynamic width & height attributes on images (attr) onLoad & resize
4. dynamic queryString on img.src (URL adds ?width=###&height=###) onLoad & resize (for demo purposes I'm using "placehold.it") this is only needed for content images in the DOM.
5. real width & height of image set to parent as max-width/height onLoad
6. debounce/throttle resize events
*/
$(function () {
$('.topic').each(function () {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')){
$('.media-support:odd').addClass('inverse');
}
});
});
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
var sizeTimer;
var images;
$(window).on('load', function () {
images = $('img');
images.each(function () {
var $this = $(this),
image = new Image(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
});* {
box-sizing:border-box;
}
html{background-color:#ecf0f1;}
body{max-width:1200px;color:#34495e;}
.content{max-width:800px;}
body,.content{margin:0 auto;}
h2{font-size:2rem;margin-bottom:15px;line-height:1;}
p{font-family:sans-serif;line-height:1.55}
img {
display:block;
max-width:100%;
height:auto;
}
.topic:nth-of-type(odd) {
background-color:#cde
}
.topic:nth-of-type(even) {
background-color:white
}
.media{
position:absolute;
transform:translateX(-100%)
}
.content{padding:35px 25px}
@media (min-width:540px){
.content {
height:350px;
padding:0;
}
.content:after {
clear:both;
content:'';
display:table;
}
.image {
background-position:center center;
background-size:cover;
background-repeat:no-repeat;
width:100%;
padding-bottom:30%;
}
.copy{
padding-left:25px;
padding-right:25px;
position:relative;
top:50%;
transform:translateY(-50%);
}
.media-support .copy {
width:50%;
float:left;
}
.media-support.inverse .copy {float:right}
.media-support .media {
width:50%;
transform:translateX(0);
float:right;
height:100%;
position:relative;
}
.media-support.inverse .media {float:left}
figure {
margin:0;
}
.media .image, .media img, .media div {
position:absolute;
bottom:0;
}
.media-support:not(.inverse) .image,
.media-support:not(.inverse) img{
left:0
}
.media-support.inverse .image,
.media-support.inverse img{
right:0;
}
.media .undock {
position:absolute;
bottom:50%;
transform:translateY(50%);
}
.media-support .media .image > img {
width:100%;
height:auto;
}
}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
<aside class="media">
<img src="//placehold.it/350x125" alt>
</aside>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</p>
<p>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</p>
</div>
<aside class="media">
<div class="image undock" style="background-image:url(//placehold.it/350x125);max-width:350px;max-height:125px"> </div>
</aside>
</article>add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f111219%2fresize-images-dynamically%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I know that this code was posted more than three years ago and you have likely learned many things since then but I'd rather not see it be a zombie any longer... so here we go:
In general the code looks okay. There aren't too many repeated blocks. There are a few suggestions I have to tidy up the code.
Cache DOM references - instead of querying for collections like
$('img')multiple times, do that once the DOM is loaded, store the collection in a variable and then reference the variable instead of re-querying.
var images
$(window).load(function() {
images = $('img');
images.each(function () {
and later in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(function () {
unused variable:
imgthis variable doesn't appear to be used anywhere after it is created:var img = new Image();. Perhaps that is left from a side venture in the code...
Don't repeat code this may only be achievable with advanced function manipulation so I wouldn't expect you to do this in one of your first projects but the code that exists in the callback function on the resize event executed for each image could be abstracted out to a separate function:
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
Then that function can be used in the load callback, utilizing
Function.prototype.apply():
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
This means
_imgWidthand_imgHeightdon't have to be declared again in the load handler, since the call tosetAttributesOnImage()handles that.
And also in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(setAttributesOnImage)
}, 250);
Also, that last timeout callback could be simplified, using
Function.prototype.bind()to create a Partially applied function:
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
Snippet
Expand the snippet below to see simplified code.
/* Goal:
1. add wrapper around .topic contents (wrapInner) onDocReady
2. add wrapper around images (wrap) onDocReady
3. dynamic width & height attributes on images (attr) onLoad & resize
4. dynamic queryString on img.src (URL adds ?width=###&height=###) onLoad & resize (for demo purposes I'm using "placehold.it") this is only needed for content images in the DOM.
5. real width & height of image set to parent as max-width/height onLoad
6. debounce/throttle resize events
*/
$(function () {
$('.topic').each(function () {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')){
$('.media-support:odd').addClass('inverse');
}
});
});
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
var sizeTimer;
var images;
$(window).on('load', function () {
images = $('img');
images.each(function () {
var $this = $(this),
image = new Image(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
});* {
box-sizing:border-box;
}
html{background-color:#ecf0f1;}
body{max-width:1200px;color:#34495e;}
.content{max-width:800px;}
body,.content{margin:0 auto;}
h2{font-size:2rem;margin-bottom:15px;line-height:1;}
p{font-family:sans-serif;line-height:1.55}
img {
display:block;
max-width:100%;
height:auto;
}
.topic:nth-of-type(odd) {
background-color:#cde
}
.topic:nth-of-type(even) {
background-color:white
}
.media{
position:absolute;
transform:translateX(-100%)
}
.content{padding:35px 25px}
@media (min-width:540px){
.content {
height:350px;
padding:0;
}
.content:after {
clear:both;
content:'';
display:table;
}
.image {
background-position:center center;
background-size:cover;
background-repeat:no-repeat;
width:100%;
padding-bottom:30%;
}
.copy{
padding-left:25px;
padding-right:25px;
position:relative;
top:50%;
transform:translateY(-50%);
}
.media-support .copy {
width:50%;
float:left;
}
.media-support.inverse .copy {float:right}
.media-support .media {
width:50%;
transform:translateX(0);
float:right;
height:100%;
position:relative;
}
.media-support.inverse .media {float:left}
figure {
margin:0;
}
.media .image, .media img, .media div {
position:absolute;
bottom:0;
}
.media-support:not(.inverse) .image,
.media-support:not(.inverse) img{
left:0
}
.media-support.inverse .image,
.media-support.inverse img{
right:0;
}
.media .undock {
position:absolute;
bottom:50%;
transform:translateY(50%);
}
.media-support .media .image > img {
width:100%;
height:auto;
}
}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
<aside class="media">
<img src="//placehold.it/350x125" alt>
</aside>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</p>
<p>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</p>
</div>
<aside class="media">
<div class="image undock" style="background-image:url(//placehold.it/350x125);max-width:350px;max-height:125px"> </div>
</aside>
</article>add a comment |
I know that this code was posted more than three years ago and you have likely learned many things since then but I'd rather not see it be a zombie any longer... so here we go:
In general the code looks okay. There aren't too many repeated blocks. There are a few suggestions I have to tidy up the code.
Cache DOM references - instead of querying for collections like
$('img')multiple times, do that once the DOM is loaded, store the collection in a variable and then reference the variable instead of re-querying.
var images
$(window).load(function() {
images = $('img');
images.each(function () {
and later in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(function () {
unused variable:
imgthis variable doesn't appear to be used anywhere after it is created:var img = new Image();. Perhaps that is left from a side venture in the code...
Don't repeat code this may only be achievable with advanced function manipulation so I wouldn't expect you to do this in one of your first projects but the code that exists in the callback function on the resize event executed for each image could be abstracted out to a separate function:
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
Then that function can be used in the load callback, utilizing
Function.prototype.apply():
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
This means
_imgWidthand_imgHeightdon't have to be declared again in the load handler, since the call tosetAttributesOnImage()handles that.
And also in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(setAttributesOnImage)
}, 250);
Also, that last timeout callback could be simplified, using
Function.prototype.bind()to create a Partially applied function:
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
Snippet
Expand the snippet below to see simplified code.
/* Goal:
1. add wrapper around .topic contents (wrapInner) onDocReady
2. add wrapper around images (wrap) onDocReady
3. dynamic width & height attributes on images (attr) onLoad & resize
4. dynamic queryString on img.src (URL adds ?width=###&height=###) onLoad & resize (for demo purposes I'm using "placehold.it") this is only needed for content images in the DOM.
5. real width & height of image set to parent as max-width/height onLoad
6. debounce/throttle resize events
*/
$(function () {
$('.topic').each(function () {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')){
$('.media-support:odd').addClass('inverse');
}
});
});
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
var sizeTimer;
var images;
$(window).on('load', function () {
images = $('img');
images.each(function () {
var $this = $(this),
image = new Image(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
});* {
box-sizing:border-box;
}
html{background-color:#ecf0f1;}
body{max-width:1200px;color:#34495e;}
.content{max-width:800px;}
body,.content{margin:0 auto;}
h2{font-size:2rem;margin-bottom:15px;line-height:1;}
p{font-family:sans-serif;line-height:1.55}
img {
display:block;
max-width:100%;
height:auto;
}
.topic:nth-of-type(odd) {
background-color:#cde
}
.topic:nth-of-type(even) {
background-color:white
}
.media{
position:absolute;
transform:translateX(-100%)
}
.content{padding:35px 25px}
@media (min-width:540px){
.content {
height:350px;
padding:0;
}
.content:after {
clear:both;
content:'';
display:table;
}
.image {
background-position:center center;
background-size:cover;
background-repeat:no-repeat;
width:100%;
padding-bottom:30%;
}
.copy{
padding-left:25px;
padding-right:25px;
position:relative;
top:50%;
transform:translateY(-50%);
}
.media-support .copy {
width:50%;
float:left;
}
.media-support.inverse .copy {float:right}
.media-support .media {
width:50%;
transform:translateX(0);
float:right;
height:100%;
position:relative;
}
.media-support.inverse .media {float:left}
figure {
margin:0;
}
.media .image, .media img, .media div {
position:absolute;
bottom:0;
}
.media-support:not(.inverse) .image,
.media-support:not(.inverse) img{
left:0
}
.media-support.inverse .image,
.media-support.inverse img{
right:0;
}
.media .undock {
position:absolute;
bottom:50%;
transform:translateY(50%);
}
.media-support .media .image > img {
width:100%;
height:auto;
}
}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
<aside class="media">
<img src="//placehold.it/350x125" alt>
</aside>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</p>
<p>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</p>
</div>
<aside class="media">
<div class="image undock" style="background-image:url(//placehold.it/350x125);max-width:350px;max-height:125px"> </div>
</aside>
</article>add a comment |
I know that this code was posted more than three years ago and you have likely learned many things since then but I'd rather not see it be a zombie any longer... so here we go:
In general the code looks okay. There aren't too many repeated blocks. There are a few suggestions I have to tidy up the code.
Cache DOM references - instead of querying for collections like
$('img')multiple times, do that once the DOM is loaded, store the collection in a variable and then reference the variable instead of re-querying.
var images
$(window).load(function() {
images = $('img');
images.each(function () {
and later in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(function () {
unused variable:
imgthis variable doesn't appear to be used anywhere after it is created:var img = new Image();. Perhaps that is left from a side venture in the code...
Don't repeat code this may only be achievable with advanced function manipulation so I wouldn't expect you to do this in one of your first projects but the code that exists in the callback function on the resize event executed for each image could be abstracted out to a separate function:
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
Then that function can be used in the load callback, utilizing
Function.prototype.apply():
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
This means
_imgWidthand_imgHeightdon't have to be declared again in the load handler, since the call tosetAttributesOnImage()handles that.
And also in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(setAttributesOnImage)
}, 250);
Also, that last timeout callback could be simplified, using
Function.prototype.bind()to create a Partially applied function:
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
Snippet
Expand the snippet below to see simplified code.
/* Goal:
1. add wrapper around .topic contents (wrapInner) onDocReady
2. add wrapper around images (wrap) onDocReady
3. dynamic width & height attributes on images (attr) onLoad & resize
4. dynamic queryString on img.src (URL adds ?width=###&height=###) onLoad & resize (for demo purposes I'm using "placehold.it") this is only needed for content images in the DOM.
5. real width & height of image set to parent as max-width/height onLoad
6. debounce/throttle resize events
*/
$(function () {
$('.topic').each(function () {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')){
$('.media-support:odd').addClass('inverse');
}
});
});
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
var sizeTimer;
var images;
$(window).on('load', function () {
images = $('img');
images.each(function () {
var $this = $(this),
image = new Image(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
});* {
box-sizing:border-box;
}
html{background-color:#ecf0f1;}
body{max-width:1200px;color:#34495e;}
.content{max-width:800px;}
body,.content{margin:0 auto;}
h2{font-size:2rem;margin-bottom:15px;line-height:1;}
p{font-family:sans-serif;line-height:1.55}
img {
display:block;
max-width:100%;
height:auto;
}
.topic:nth-of-type(odd) {
background-color:#cde
}
.topic:nth-of-type(even) {
background-color:white
}
.media{
position:absolute;
transform:translateX(-100%)
}
.content{padding:35px 25px}
@media (min-width:540px){
.content {
height:350px;
padding:0;
}
.content:after {
clear:both;
content:'';
display:table;
}
.image {
background-position:center center;
background-size:cover;
background-repeat:no-repeat;
width:100%;
padding-bottom:30%;
}
.copy{
padding-left:25px;
padding-right:25px;
position:relative;
top:50%;
transform:translateY(-50%);
}
.media-support .copy {
width:50%;
float:left;
}
.media-support.inverse .copy {float:right}
.media-support .media {
width:50%;
transform:translateX(0);
float:right;
height:100%;
position:relative;
}
.media-support.inverse .media {float:left}
figure {
margin:0;
}
.media .image, .media img, .media div {
position:absolute;
bottom:0;
}
.media-support:not(.inverse) .image,
.media-support:not(.inverse) img{
left:0
}
.media-support.inverse .image,
.media-support.inverse img{
right:0;
}
.media .undock {
position:absolute;
bottom:50%;
transform:translateY(50%);
}
.media-support .media .image > img {
width:100%;
height:auto;
}
}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
<aside class="media">
<img src="//placehold.it/350x125" alt>
</aside>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</p>
<p>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</p>
</div>
<aside class="media">
<div class="image undock" style="background-image:url(//placehold.it/350x125);max-width:350px;max-height:125px"> </div>
</aside>
</article>I know that this code was posted more than three years ago and you have likely learned many things since then but I'd rather not see it be a zombie any longer... so here we go:
In general the code looks okay. There aren't too many repeated blocks. There are a few suggestions I have to tidy up the code.
Cache DOM references - instead of querying for collections like
$('img')multiple times, do that once the DOM is loaded, store the collection in a variable and then reference the variable instead of re-querying.
var images
$(window).load(function() {
images = $('img');
images.each(function () {
and later in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(function () {
unused variable:
imgthis variable doesn't appear to be used anywhere after it is created:var img = new Image();. Perhaps that is left from a side venture in the code...
Don't repeat code this may only be achievable with advanced function manipulation so I wouldn't expect you to do this in one of your first projects but the code that exists in the callback function on the resize event executed for each image could be abstracted out to a separate function:
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
Then that function can be used in the load callback, utilizing
Function.prototype.apply():
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
This means
_imgWidthand_imgHeightdon't have to be declared again in the load handler, since the call tosetAttributesOnImage()handles that.
And also in the resize callback:
.on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(function () {
images.each(setAttributesOnImage)
}, 250);
Also, that last timeout callback could be simplified, using
Function.prototype.bind()to create a Partially applied function:
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
Snippet
Expand the snippet below to see simplified code.
/* Goal:
1. add wrapper around .topic contents (wrapInner) onDocReady
2. add wrapper around images (wrap) onDocReady
3. dynamic width & height attributes on images (attr) onLoad & resize
4. dynamic queryString on img.src (URL adds ?width=###&height=###) onLoad & resize (for demo purposes I'm using "placehold.it") this is only needed for content images in the DOM.
5. real width & height of image set to parent as max-width/height onLoad
6. debounce/throttle resize events
*/
$(function () {
$('.topic').each(function () {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')){
$('.media-support:odd').addClass('inverse');
}
});
});
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
var sizeTimer;
var images;
$(window).on('load', function () {
images = $('img');
images.each(function () {
var $this = $(this),
image = new Image(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
});* {
box-sizing:border-box;
}
html{background-color:#ecf0f1;}
body{max-width:1200px;color:#34495e;}
.content{max-width:800px;}
body,.content{margin:0 auto;}
h2{font-size:2rem;margin-bottom:15px;line-height:1;}
p{font-family:sans-serif;line-height:1.55}
img {
display:block;
max-width:100%;
height:auto;
}
.topic:nth-of-type(odd) {
background-color:#cde
}
.topic:nth-of-type(even) {
background-color:white
}
.media{
position:absolute;
transform:translateX(-100%)
}
.content{padding:35px 25px}
@media (min-width:540px){
.content {
height:350px;
padding:0;
}
.content:after {
clear:both;
content:'';
display:table;
}
.image {
background-position:center center;
background-size:cover;
background-repeat:no-repeat;
width:100%;
padding-bottom:30%;
}
.copy{
padding-left:25px;
padding-right:25px;
position:relative;
top:50%;
transform:translateY(-50%);
}
.media-support .copy {
width:50%;
float:left;
}
.media-support.inverse .copy {float:right}
.media-support .media {
width:50%;
transform:translateX(0);
float:right;
height:100%;
position:relative;
}
.media-support.inverse .media {float:left}
figure {
margin:0;
}
.media .image, .media img, .media div {
position:absolute;
bottom:0;
}
.media-support:not(.inverse) .image,
.media-support:not(.inverse) img{
left:0
}
.media-support.inverse .image,
.media-support.inverse img{
right:0;
}
.media .undock {
position:absolute;
bottom:50%;
transform:translateY(50%);
}
.media-support .media .image > img {
width:100%;
height:auto;
}
}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
<aside class="media">
<img src="//placehold.it/350x125" alt>
</aside>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</p>
<p>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</p>
</div>
<aside class="media">
<div class="image undock" style="background-image:url(//placehold.it/350x125);max-width:350px;max-height:125px"> </div>
</aside>
</article>/* Goal:
1. add wrapper around .topic contents (wrapInner) onDocReady
2. add wrapper around images (wrap) onDocReady
3. dynamic width & height attributes on images (attr) onLoad & resize
4. dynamic queryString on img.src (URL adds ?width=###&height=###) onLoad & resize (for demo purposes I'm using "placehold.it") this is only needed for content images in the DOM.
5. real width & height of image set to parent as max-width/height onLoad
6. debounce/throttle resize events
*/
$(function () {
$('.topic').each(function () {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')){
$('.media-support:odd').addClass('inverse');
}
});
});
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
var sizeTimer;
var images;
$(window).on('load', function () {
images = $('img');
images.each(function () {
var $this = $(this),
image = new Image(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
});* {
box-sizing:border-box;
}
html{background-color:#ecf0f1;}
body{max-width:1200px;color:#34495e;}
.content{max-width:800px;}
body,.content{margin:0 auto;}
h2{font-size:2rem;margin-bottom:15px;line-height:1;}
p{font-family:sans-serif;line-height:1.55}
img {
display:block;
max-width:100%;
height:auto;
}
.topic:nth-of-type(odd) {
background-color:#cde
}
.topic:nth-of-type(even) {
background-color:white
}
.media{
position:absolute;
transform:translateX(-100%)
}
.content{padding:35px 25px}
@media (min-width:540px){
.content {
height:350px;
padding:0;
}
.content:after {
clear:both;
content:'';
display:table;
}
.image {
background-position:center center;
background-size:cover;
background-repeat:no-repeat;
width:100%;
padding-bottom:30%;
}
.copy{
padding-left:25px;
padding-right:25px;
position:relative;
top:50%;
transform:translateY(-50%);
}
.media-support .copy {
width:50%;
float:left;
}
.media-support.inverse .copy {float:right}
.media-support .media {
width:50%;
transform:translateX(0);
float:right;
height:100%;
position:relative;
}
.media-support.inverse .media {float:left}
figure {
margin:0;
}
.media .image, .media img, .media div {
position:absolute;
bottom:0;
}
.media-support:not(.inverse) .image,
.media-support:not(.inverse) img{
left:0
}
.media-support.inverse .image,
.media-support.inverse img{
right:0;
}
.media .undock {
position:absolute;
bottom:50%;
transform:translateY(50%);
}
.media-support .media .image > img {
width:100%;
height:auto;
}
}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
<aside class="media">
<img src="//placehold.it/350x125" alt>
</aside>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</p>
<p>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</p>
</div>
<aside class="media">
<div class="image undock" style="background-image:url(//placehold.it/350x125);max-width:350px;max-height:125px"> </div>
</aside>
</article>/* Goal:
1. add wrapper around .topic contents (wrapInner) onDocReady
2. add wrapper around images (wrap) onDocReady
3. dynamic width & height attributes on images (attr) onLoad & resize
4. dynamic queryString on img.src (URL adds ?width=###&height=###) onLoad & resize (for demo purposes I'm using "placehold.it") this is only needed for content images in the DOM.
5. real width & height of image set to parent as max-width/height onLoad
6. debounce/throttle resize events
*/
$(function () {
$('.topic').each(function () {
var $this = $(this),
ifMedia = $this.find('.media');
$this.wrapInner('<section class="content"/>');
if (ifMedia.length) {
$this.addClass('media-support');
}
if ($this.hasClass('media-support')){
$('.media-support:odd').addClass('inverse');
}
});
});
function setAttributesOnImage() {
var $this = $(this),
_imgWidth = $(this).width(),
_imgHeight = $(this).height();
$this.attr({
'width' : _imgWidth,
'height': _imgHeight,
'src': '//placehold.it/' + _imgWidth + 'x' + _imgHeight
});
}
var sizeTimer;
var images;
$(window).on('load', function () {
images = $('img');
images.each(function () {
var $this = $(this),
image = new Image(),
_naturalWidth = this.naturalWidth,
_naturalHeight = this.naturalHeight;
image.src = $(this).attr("src");
setAttributesOnImage.apply(this);
$this.wrap('<figure class="image" />').closest('.image').css({
'max-width': _naturalWidth,
'max-height': _naturalHeight
});
});
}).on('resize', function () {
clearTimeout(sizeTimer);
sizeTimer = setTimeout(images.each.bind(images, setAttributesOnImage), 250);
});* {
box-sizing:border-box;
}
html{background-color:#ecf0f1;}
body{max-width:1200px;color:#34495e;}
.content{max-width:800px;}
body,.content{margin:0 auto;}
h2{font-size:2rem;margin-bottom:15px;line-height:1;}
p{font-family:sans-serif;line-height:1.55}
img {
display:block;
max-width:100%;
height:auto;
}
.topic:nth-of-type(odd) {
background-color:#cde
}
.topic:nth-of-type(even) {
background-color:white
}
.media{
position:absolute;
transform:translateX(-100%)
}
.content{padding:35px 25px}
@media (min-width:540px){
.content {
height:350px;
padding:0;
}
.content:after {
clear:both;
content:'';
display:table;
}
.image {
background-position:center center;
background-size:cover;
background-repeat:no-repeat;
width:100%;
padding-bottom:30%;
}
.copy{
padding-left:25px;
padding-right:25px;
position:relative;
top:50%;
transform:translateY(-50%);
}
.media-support .copy {
width:50%;
float:left;
}
.media-support.inverse .copy {float:right}
.media-support .media {
width:50%;
transform:translateX(0);
float:right;
height:100%;
position:relative;
}
.media-support.inverse .media {float:left}
figure {
margin:0;
}
.media .image, .media img, .media div {
position:absolute;
bottom:0;
}
.media-support:not(.inverse) .image,
.media-support:not(.inverse) img{
left:0
}
.media-support.inverse .image,
.media-support.inverse img{
right:0;
}
.media .undock {
position:absolute;
bottom:50%;
transform:translateY(50%);
}
.media-support .media .image > img {
width:100%;
height:auto;
}
}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
<aside class="media">
<img src="//placehold.it/350x125" alt>
</aside>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
</div>
</article>
<article class="topic">
<div class="copy">
<h2>This is a section heading</h2>
<p>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</p>
<p>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</p>
</div>
<aside class="media">
<div class="image undock" style="background-image:url(//placehold.it/350x125);max-width:350px;max-height:125px"> </div>
</aside>
</article>edited 26 mins ago
answered 31 mins ago
Sᴀᴍ Onᴇᴌᴀ
8,29861853
8,29861853
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f111219%2fresize-images-dynamically%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown