 All right, let's go ahead and get started. So hi, everyone here for intro to Jumla? Okay, good answer. So hi, I'm Abby Milberg. I'm a front-end architect at Third & Grove, which is a full-service digital agency primarily specializing in Drupal. And we're here today to talk about some things you can do in Drupal 8 to make images a little more interesting and give a little more control. So our goal here, and a couple bullet points, we want to give our content creators a little more control. We want to keep the site consistent, performant, and secure. So I think we've all had that project where the client wants a lot of control over images and then that winds up taking the form of putting it in CK Editor and it's either 6,000 pixels wide or it's dimensions that don't go with the site, it doesn't have margins, all of these things, right? So we don't want that. We do want some consistency, but we still want to give the client or the content editor that power as well as the designers, which has also driven a lot of this in my experience. So today we're just going to talk about a couple examples of ways that I found over a number of projects to do that and hopefully you'll be able to take home the code, see the config, and use some of that in grown projects. This is going to be pretty light on slides. It's going to be very heavy on code, but I'm going to make the code and the config in a feature all available on GitHub after the talk so you don't have to worry about trying to copy down every pre-process function line for line while you're sitting here. Okay. Just as a brief sort of to frame the issue, Drupal 8 has given us a lot of power with images that we never had in core before. You've got break point in core, you've got responsive images in core, you've got media in core with the help of some contrib modules, but once you get that set up, it's really powerful. So these things give us a great foundation to build upon even from the get go that we didn't have out of the box in Drupal 7. Again the question here, should all images be treated the same? When your client, your author has a blog post and an image field to go with it, do they all really need the same crop? Does that make sense for all content? Probably not. So we're going to give them some ways to fix that. The first example I'm going to go over is on using a CSS class generated by a list field to control the spacing of your images. So I've used this primarily when I've been working with grids and it works with small images generally, things like logos, things like SVGs, things that you may not want to ever crop because you don't want to cut off some of the space, part of a logo, that sort of concern. So small images where it may be appropriate to use CSS. So I'll go over an example of this. So I've uploaded here, this is an example of an image grid without anything in place. We've got an image style applied that is making all of these images the same width. I think somewhere my design lead who's not here just shuddered in horror because those don't look even, even though according to the rules of the same width, they are. And you also wouldn't want to put a crop on them. You wouldn't want a scaling crop style where you saw half of a can or half of a football. That wouldn't make any sense. So the effect we're going for is something more like that. And this is a very rudimentary example. But it's pretty easy to pull off with a few lines of code. So I'm going to show you what this looks like from the author's perspective and then we can dig a little deeper into the config and the preprocess functions involved. So this is the node that holds the aerosol can image you saw before. I've created a drop-down field here where you can choose its width. Is it default? Is it wide? Is it narrow? And that's all that that is from the perspective of the content editor. If we go into structure here, you can see this is really just a plain image field and a list text field. Sorry. And for display of the teaser, we're rendering the image orientation as a key. Now, you could render it however you wanted, but the technique that I'm using here is all we're doing is with this preprocess function on the node, we're getting the value of that field with the image orientation. And we're adding it along with an orientation modifier to the classes array. And then we're hiding the field itself. And in this instance, all I have, that doesn't even require a custom, no, that actually doesn't even require anything custom in the template. All I've got going on here is some really basic CSS, max with 40, 75, 90. And obviously those could be modified to your exact purposes. And in this case, I also did apply an image style because when we're using CSS to make things smaller, we still don't want to be making that 6,000 pixel image smaller. So I am applying an image style here, which is just a scale, a scale style down to 300 pixels, something along those lines, so that it's not taking a hit on performance. So that has helped us a lot, especially on the homepage of our own site. We had a big grid of client logos. And when it looks like this, it's just not good. So that one is probably the simplest example I'm going to show. The next one I want to show is letting the user choose the actual image style from a dropdown. And by this I mean predefined Drupal image styles that you're used to. And we're using a similar technique, I'll show you it in an example first. The screen is a little small, but I've got my image field here. And I've also done one as media, just I'll demonstrate the code for both if you're using a generic image field or a media field. And I've given it two options, one that I'm calling landscape, one that I'm calling portrait. And when we get to the structure of that, you can see that the fields themselves are pretty much as you would expect. And when we manage the display, we're using default on this one. We've got the image itself, rendering as an image, and I'm applying a default style to it, just in case. We've also got the image style value as a key. And I've created, again, a media field here. It's important to note there are lots of ways to use media fields with their own display modes, but in this instance, the simplest solution for me has been to render it as a thumbnail which lets you apply an image style right here at the content type level. So if we go into the code here, let's take this one at a time. So just like we did in the earlier example, we're getting the value of the image style itself out of the key there. And we're using a pre-process function where for both that image field and that image media field, we're able to simply replace the image style. And this doesn't require any templates. This doesn't require anything more complicated. So if we go back to the browser, and I change this to landscape, now it's landscape, both of them. That's the slide for everything I just said. Okay, so the next one is where we start to get a little trickier here. So in Drupal's picture module with the responsive images, we have this great ability to apply different image styles at different break points. And we can even use modules like focal point to set the exact spot that we want to make sure doesn't get cropped in each instance. But what if we wanna do a completely different image at different break points? So has everyone lost the battle of no, you shouldn't put the text on the image for your website hero? Right, so that's one where the image style for the smaller one doesn't work. I don't like doing it. I've, yeah, doesn't matter. So this is a way to basically let the user fill in multiple fields for those different break points if they insist. So I will say a thing about accessibility in this case. This is not semantically correct if your images are drastically different from each other in terms of content. Or if the same alt text can't be reasonably applied to both images, this isn't what you should use in that case. This is for cases where you've got your banner image and they've made the text centered and bolder on mobile or things along that line. If it's totally different, that's not what the picture element is for. So please just keep accessibility in mind. In this example, I'm using too drastically. I say that because I'm about to use two drastically different images just to demonstrate what this does. So we're getting smaller. And now you've got a completely different image there from a different field. From the content editor standpoint, all this looks like is they have a large image field. They have a small image field. You could add more break points to this if you wanted using the same principles. I've chosen to make the small image field optional normally because I find that making fields required comes back to by you if they don't absolutely need to be. So this gets a little trickier in the preprocess. But we will walk through it. So in this instance, yeah. So first of all, the large image field I made required. I made at least one of the images fields required, although again you could modify this just to skip over all of it if neither of them was filled in. So I'm loading using the image style load function, the hero wide image style of the URI of that image. Since the small image field is optional, I'm using an if else statement to check for it and then set it appropriately. So if it is set, we're loading that image with the, or that images URL with the narrow break point, or sorry, the narrow image style. And if the small field is not filled in, we're applying the narrow image style to that larger image, just like it would be if you did break point functionality out of the box. And now we're passing these URLs to the template. It's not my preference to do this sort of thing in the template, but I haven't found a reliable way to build these picture tags in a preprocess function. If anyone can improve on that, that'd be great. I'm also passing the alt text of the large image field. As I said, we wanna make sure we're using alt text. The picture element in HTML doesn't allow for different alt text of the different sizes. So right here, I've in the content type made alt text required for the large image but hidden it all together for the small one. So this one we are going to go into the template and just build our picture tag. Oh, I left out one step, which is the break point. So Drupal 8 also has break points built in that you can use across modules, across themes. You use them if you're doing responsive images in the quote unquote out of the box way. So we're gonna use those same break points and leverage them in this so that we can keep it consistent across our site. You could hypothetically put this directly in the theme but there's not much of a reason to. So these last few lines in this preprocess function are to get all of the break points out of that hero image group that I've created here. Now this happens to be minimal because I only needed one for the demo and set it as a variable, get the media query, set it as a variable to pass to the template. And now what we have is a picture tag like you've probably seen before. Only it's using the two fields. Cropping, who could tell who it is? So yeah, so there's a lot going on with cropping and triple and part of the reason we're providing all of these choices around image styles and everything are to alleviate some of those situations where you're forced to crop the image that's 10 people in a row and you have to crop it into a tall, narrow image style and that just messes with things. But sometimes you do need a style. So I'm gonna talk about several ways to handle things to get around some of the issues that come up with that. So has everyone used the focal point module? If, yeah, great. So if you haven't used the focal point module, I highly recommend it. I've been using it since Drupal 7. What it lets you do, I will show really quickly. There seem to be... Cashing hits you at the worst time, doesn't it? Okay, so if you can see, maybe I'll try and zoom in on this a bit. Can everyone see the plus sign here on the middle of the image? So with a focal point image style, when you upload the image, it lets you drag this little crosshair around on the image itself and what that tells it is that on any focal point image style, it should retain that part when it crops. So if I use a scale and crop image style, normally in Drupal by default, that'll just scale and crop towards the center, which doesn't help me if somebody's face is on the left. So in this sort of instance, I could tell it to crop on the left. So if I do that here now and save it and wait for caches to clear, you can see now that that picture's been cropped all the way over to the left where I put that. So that's a great out-of-the-box, or it's a fantastic contrib module. I've found it works incredibly well in a great many situations. I have however had some situations where we couldn't use the focal point module either because the client's company had very strict policies about contrib modules or because perhaps we were uploading a lot of images via a script and there was never gonna be a person actually going through and picking those focal points. And sometimes if you're lucky in those cases, you know the part of the image that you probably want to be kept more often. Maybe you know that people's faces tend to be towards the top or in these situations, they're normally not ideal, but if you want to systematically mimic the focal point functionality without having it, you can try to do so. So this is a problem I've been having for a long, a very long time, and there's a couple approaches. So when you're creating an image style in Drupal, if you just create a crop style, and I'm sure you've all done this, if you create a crop style, you can, that's what I named them all, right, yeah. You create a crop style, you can choose your anchor point and it's great. But if you create a scale in crop style, you don't have that option. So what everyone thinks at first, myself included in many cases, learned to the hard way, was well I'll just scale it to the width or height that I want and then I'll crop the other dimension, right? So what happens when your image is not the orientation that you assumed it would be? I'll show you real quick if anyone hasn't seen it. So let's say what I really want my images to be is 300 wide by 400 tall and I'm assuming they're all coming to me as portrait oriented images, right? So I scale them down to 300 wide and I crop them to 400 tall, which will let me choose my nice top anchor point and I get that really nice black box as a bonus feature. Yeah, it's a thing, it's a thing. We've been there many times. So how do you get around that situation? You basically have, what you have is you need different behaviors based on the dimensions of the image that the user has uploaded, right? It depends whether it's wider than it is tall or vice versa or possibly even a more specific ratio than that depending on your image size. So what I've got here is some pre-process function, a pre-process function that lets us detect what those dimensions are and then potentially, potentially modify the image style as appropriate. So in this case, I'm fetching the value of the image field and its height and width are actually right there in the array. You don't need to do anything funky to calculate them or anything. It's just the height and width of the image that was generated, that was uploaded, not cropped or anything, the uploaded image. And then we're just calculating a ratio here. So in my example, I'm saying that I want, in this example, a square image, at the end of the day. So the ratio that I'm testing for is one. But if I had a different image ratio that I wanted as the outcome, let's say I wanted a two to three ratio, what I would need to test for would be if it met that two to three ratio or if it went over. Does that make sense? Okay. So I think you can see here, I'm using the same technique I used above with swapping out image styles. Only now I'm testing for that ratio. And the cool thing about this one is the user doesn't actually have to, and by user I mean content editor, they don't actually have to do anything to make this happen. This isn't like the other examples where they had to choose. It just happens automatically through that preprocess. So let's look at this example. We've got a test image. I've got a square image style applied to it. And you can see when I uploaded that, that was a landscape image. Now if I go back to my image styles, ASDF, so I had profile default and profile alt. Profile default is assuming, I'm assuming that that is a landscape image and that I wanna crop it in from the center and it'll be 400 by 400. Crop and scale 400 by 400. That's normal. We can do that. But in that preprocess function, we're saying if it's taller than it is wide, I want it to first scale the width to 400 and then crop up. So this one is just cropping in as you would expect. But if we switch it out for, so we're gonna switch it out for this image that's vertical and that is my brother and I did put that there to embarrass him. He's not in Drupal. But so this is the sort of image where we would want it to crop upwards and please ignore the focal point thing there because it's there because I'm using focal point elsewhere. And we're not actually using it in this case. So I put it down here and it wouldn't matter. And now you can see it automatically cropped towards the top of that image. The next example I would like to talk about, my slide's still a thing, background images. All right, so we love, we have designers and clients and everyone who love to have background images and heroes and things like that. And I mean, it makes complete sense from a design perspective, right? Especially we can use background cover and CSS. It's, you get into a whole nother set of issues if you're trying to use an inline image that you want to cover an unknown amount of space. It's just can be messy, depending again on aspect ratios. But Drupal doesn't give us a great way to handle background images out of the box. I think many folks here have probably done the same that I have many times in just getting that background URL out of a pre-process function and sticking it in an inline style tag. And I admit that that is part of what I'm about to show you. But the thing that always bugs me about that is that it's not performant on a smaller device, right? Because an inline background image like that will load no matter what size you're looking at. It doesn't matter if you've got display, not on the div, it doesn't, you know, it's just, it's gonna load if it's in there. And that's no good if you've got a background image that's gonna look good on somebody's full size desktop. So in this instance, I'm again using multiple fields to set different background images or is it, sorry, this one's not multiple fields, although you could do that. This one, I'm applying multiple image styles to the same image at multiple sizes at multiple viewport widths and we're gonna use a little bit of JavaScript to swap them out progressively so that we don't load those giant images when we don't need to. So if you look carefully, if you look carefully here for a second, I've got this moose set as a background image on this div and I'm gonna make it smaller and all of a sudden the image style changed. It wasn't smooth. You can see, you can see where it changed, right? It jumped, there it is. So that's what we're gonna do here and the markup I will show really quickly before trying to dive into the preprocess. What we're gonna use is a data attribute and an initial inline style. Is that, that's a little hard to read but it's about as big as I could get it but I've got an initial inline style right there that is the smallest size of the image. It's the size that you would need on your average smartphone and then I've got a couple data attributes here of the image at larger sizes and we're gonna use some JavaScript. So let's go back to that to our code. All right, so this is pretty much, we're getting used to this, right? Getting the images with the image style out of the preprocess function. So we're getting out of a media field this time just to show that you can get these values out of either. We're getting two versions of it, same image field, we're gonna get it with the two different image styles applied and the URL of that, the raw URL. At this point I am going to start applying these things as attributes. So I'm using in this case attributes on the node itself just because that's all I was doing with this demo but you could put these anywhere in the markup you want. You could put these on a different field within the same node, you could put these on a random div that you placed in your twig file. It really doesn't matter but at the core of it I'm defaulting to the small URL, just inline CSS just like I was complaining about a minute ago. And I'm also creating two background or two data attributes, background small, background large. Oh, and I am, yes, adding a class. Adding a class to it has responsive background just so that we can key off of that for our JavaScript later. So the JavaScript on this one. That's the trick here, right? Cause I hate using JavaScript for basic visual things like this, right? But I wound up weighing my hatred of using JavaScript for something this minor versus my hatred of loading a 3000 pixel wide background on someone's iPhone, the JavaScript one. So the cool thing is a lot of this is, Drupal gives us some great tools like the debounce function built in so I was able to not worry about that when somebody's resizing their browser like crazy, like only front-end developers do. I don't know. But, you know, let's be honest. But yeah, so what I'm doing, I'm finding the div with these attributes applied. I'm defaulting, I've got a variable here called small viewport. I'm defaulting to assuming that it's the small value which I've chosen in this case is 768. You could do this with as many different breakpoints or any breakpoint that you choose. May the odds be in your favor. And I'm defining what I want that inline CSS to be in both of those cases. So when we're on the small viewport with, I'm gonna, you know, this is the variable. I'm gonna apply the small background. Ditto for the large one. Yeah. Oh, that's what, okay, sorry. If you've got this, if you don't have the small viewport, we're gonna apply the large CSS. So that's happening on load. Since on load I've got the inline style showing the small image by default. All this is doing is on page load checking if we don't have document width of less than 768. Again, this is a boolean here. Then we're gonna swap out the style tag for the style attribute for the large background. The trickier part is listening on resize. Please, please, please debounce this. Don't make it worse than loading the 3000 pixel image. I've got, again, I'm debouncing this every quarter second I chose. If you're, this is again checking if we're on the small or large size. And we also have the small viewport. Weather, yeah. If the state matches the existing state, we don't need to know. So we don't need to do anything if we resized, but before it was 400 pixels and now it's 430. It doesn't matter. So we're returning out in that instance. However, if they don't match, we're setting the appropriate style for the new state. And then we're calling it on resize. Everyone with me? I have not discovered a completely clean scenario for these background image options, but this is one I've found that seems to be more performant than most. If, yeah, I would be very interested if anyone has found another approach to that. Okay. All right, SVGs, next topic. Nope, SVGs. So I gave an earlier version of this talk at last year's Drupal GovCon. And when I did that, and when I wrote my application for this talk, there was really no good, there was no non-beta contrib solution or core solution to using SVGs as images in Drupal. And that's been a real struggle. I think a lot of people have dealt with, especially designers and clients. And it's just not being able to have an SVG as an image in this day and age was, I think, a serious shortcoming for Drupal. And I had a lot of methods I'd worked out to work around that. And then in January, a really cool contrib module went stable called SVG Image. And I had to rewrite half my talk. But no, in all seriousness, it's a fantastic module. I've worked with it on client sites. And it does exactly what you would want in at least 99 out of 100 cases for it to do, which is it just lets you make SVG an accepted extension of on your image field, your existing Drupal image field. So I'm gonna show you how that works real quickly. And then we're gonna talk about a few other things to keep in mind about SVGs. So this is just, and this is just your run of the mill Drupal image field. I've got my alt text. There it is. So that is the size that it uploaded. You saw that that planet was completely distorted. That right there is the viewbox that the SVG came with out of the box. When you're setting up this content type, there are a few things, or this field in a content type, there are a few things you can do about this. So as I mentioned, it just lets you add SVG as an acceptable extension right here. When you manage display, you get your normal image style choices, the SVG will ignore them if you put an SVG in this field, but they will still apply to your other ones. I was worried when I first saw this that it was gonna spit some horrible error if I tried to put an image style here, and it functions beautifully. You can set image dimensions here for the SVG if you want to force them to be the same size. That depends on your use case, whether that's gonna be a good idea for you. In my cases, I haven't wanted always to force them to be the same size, but I've also had pretty good control over what got uploaded. So it depends, and this is one of those scenarios where I found that choosing image orientation CSS trick to be really useful as well. You can also choose whether you want to render, I'll make this bigger, whether you want to render the SVG as an image or as an SVG tag. So that can be really cool or really dangerous. So I'm gonna turn this off now, I'm gonna let it render as an SVG tag and show you. Okay, so there's the phone. Here it is as an SVG tag, I should say. So nothing about this has changed from the file I uploaded. If I pulled that file, that SVG file from my computer open in sublime text, it would be the exact same thing. You can see the automated Adobe Illustrator generated thing. What you see is what you get here. So in this instance, it's pretty good. I happen to know that I can trust that image. The thing to keep in mind about SVGs, and to be clear, I'm not saying don't do this, but the danger with rendering them inline as opposed to as images is that an SVG file is really a document in its own right. It's not really an image format. You can put JavaScript in an SVG file, just stop and think about security for a minute. So again, that may be one of those situations where it depends on those use cases, but a lot of it in those scenarios is gonna come down to how much do you trust all of your content editors? And by trust, I don't just mean their intentions. Hopefully nobody malicious, hopefully it has access to your site, but they're tech savvy. I can go Google for SVGs on Google Image Search and come up with goodness knows what, and I might really not want it on my site. So just be very careful if you're gonna do that. Make sure there's a good reason and that you have some sort of review process in place and that you and your client are aware of the risks and choosing to accept them with knowledge. That said, there's some really cool things you can do with CSS with these inline SVGs, it's great. On the other hand, given that these are nodes, these are fields in nodes, normally you're not gonna be styling them on a one-off basis. So I'm sure there are use cases, but I think most of the time you probably don't need an inline SVG, but using them as images is fantastic. And by all means, don't take me as the gospel on SVG security, just keep in mind, look it up if you're gonna do it. And that is, by the way, over here in that same image grid, well it doesn't look very fancy because it's such a small image to begin with, but this is a mixture of SVGs and bitmaps, so, or not bitmap, you know what I mean. Pinks and JPEGs and GIFs. So, I believe that that is it for my slides. The last parting thought here is modify anything you saw above. Mix, match, you know, change the number of breakpoints, change the number of styles, combine them, make it your own. I hope that you can take away from this talk not just what I showed specifically, but also some general approaches. And I'll get questions in one second, but if you have to leave, I understand, and you can find all of the code, all the config and code that I showed on GitHub at abbey805-d8-images. So, thank you all so much. Questions, please. Yes, hi. I'm wondering if you've had any experience with the ImageFX module in Drupal 8. Its predecessor, ImageCache Actions, allows you to, within the image styles area, to choose aspect ratios, to choose which styles you apply. Last morning. I haven't had a chance to work with that one in D8, no. I would be very interested to talk about it, though. Sorry, thanks. Oh, so, what was it? ImageFX in Drupal 8 and its ImageCache Actions in Drupal 7. I've done ImageFX. Yeah, thank you. I just wanted to point out that we, at Eastern Standard, have a solution for that responsive background thing that you were talking about. We have a library, it's called Responsive Backgrounds, and it essentially uses the picture module. So, you just have one image and you'll apply the crops we're using. What's that? Not crop API, but image widget crop. So, you'll just set all of your images based on, like, all right, on mobile, I want it to look like this. Tablet on this, desktop on this, and then all you do in your template is spit out the picture tag. And then in JavaScript, you just say, all right, in this CSS class, look for the picture module, and it does essentially what you're doing. And it's more flexible in that you don't have to go into JavaScript and actually manually just, like, add those breakpoints in. It's more flexible that way. You could just define your breakpoints, like, straight off the bat, if you want us to send you that. Oh, that'd be great. Thank you. Is it on Drupal.org? No, no, no, it's just a JavaScript library, but it just leverages that. We've been using it since seven, so. That sounds great. Thank you. Totally. Any other? What I can do is just share it with her and then maybe she can share it with other people. But it's something that we created, like, in-house for that. It's just a JavaScript library that just, again, looks at that picture tag and it already has, like, if you have used a picture tag, it knows, like, the picture tag will say, okay, this image will be used in this media query that you defined or whatever. So it'll just, like, look at that and then responsibly, like, change those things out. So it's not, like, as hard-coded as, like, the example above where it's, like, you can actually manage it in your config or in Drupal. So I'm not sure how we can spread that out, but we'll figure it out. Great, thank you. So you were talking about accessibility earlier and I went to training yesterday and they were talking about the frustrations of background images and CSS and the lack of alt tags. And is there any, did we find any workarounds for that? So I went to a fantastic talk earlier from a gentleman who could probably speak to this much better than I, but I found a couple things. I mean, A, if it's content in the sense that you can't miss it and still have the meaningful result on the page, it, or experience of the page, it's probably, it probably shouldn't be a background image. I, if anyone want, you know, I'd be interested to hear other takes on that, but I think of some, if it has text on it that should be alt captioned, if it's just important content, I think it probably belongs in an image tag. If it's the flowery meadow in the background of your hero image, like, I don't know what the thoughts are on whether that needs to be, you know, made it as accessible, I guess. I do know there are some ARIA tags also that can be used to label things, but I am honestly not sure if that's best practice. So, yeah. Hi. Hi. Oh, thank you for your nice talk about this interesting topic about creating these file formatters, right, which have state now, and file formatters are supposed to not have any state, which is something the core ships with, and there are limitations why you would want to kind of style images one way or the other. Do you have any ideas about if this idea is generic enough for files also? So, for example, I have a CSV file, and I can, based on the size, I can choose to either display it in line in the browser or make it available only for downloads. I think they can do that already. Like, when you render a file in a view mode, just a file field, you can choose between displaying in line or displaying a link, but that's probably limited by format. Right, but... I can't speak as much to non-image. I see. So I'm thinking, yes, you can set the formatter, but it's global. I want to let the editor set it on a file per file basis, whether they want to display it one way or the other. CSV is just an example, but can be extended to other kinds of things. Yeah, I mean, I think anything that Drupal allows you to choose between various modes of display, you could alter that mode of display in a pre-process function, but there are certain file types that just won't render in a browser. Sure. So, yeah. All right, thank you. Yeah, thank you. All right, well, unless there's anything else, thank you all so much for listening and appreciate it. Thank you.