In responsive websites, we usually keep different breakpoints for different devices & different breakpoints require different image sizes. There are different ways to use images in responsive layouts.
- Same image on all Devices
- Manual upload of device specific Image
- Generate images on Fly.
- Tridion CID
Same image on all devices: This is simplest of all as point of development, let user upload single image and same image is published on delivery. But there are few points which needs to be taken care for this.
UI Designer has to maintain the aspect ratio in his designs across Desktop, tablet, mobile or whatever breakpoints you have. e.g
Desktop: 200 : 100
Tablet: 100 : 50
Mobile: 50: 25
so if you see the aspect ration has been maintained at 2:1. so Maintaining aspect-ratio is very important as it can go haywire if the objects start scaling based on the screen dimension. To maintain aspect ratio of the objects, select Auto for either width or height of the object in the Primary view
Tridion side there is no special change is required. normal image publishing.
Cons: Mobile has to download the same big image, which could be bandwidth issue, also in sites where lots of images are used, this approach on tablet/mobile would not be considered best
Manual upload of device specific Image: There are different reasons where device specific images are required:
- Designers are not totally versed with it. so ratios are not maintained across devices
- Performance and bandwidth issue
- For mobile instead of whole image only part of image is required for more cleared and focused view.
these images could be manually-generated or from some DAM System.
Tridion Implementation:
Create a category with Keywords having device information.
Category : Device Type
Keywords - large, medium, small
Create a embedded schema "Responsive Multimedia" as shown below
ScreenSize refer above category.
For this we created a generic helper class in razor, it generate the Data-Interchange tags in images. We are using Foundation Framework for handle responsiveness of site here.
<img data-interchange="[@Publication.MultimediaUrl/@mobile, (default)], [@Publication.MultimediaUrl/@tablet, (medium)], [@desktop, (large)]"></img>
Now you can read the component and read the values of uploaded images and generate the image tag with data-interchange as shown above.
Generate images on Fly Other approach is to upload a single image and generate the rest of the device specific images on Fly using custom code. But design should maintain aspect ratio of the images.
Tridion code: we have written a c# tbb to handle it, here is the code for it. you can customize it
[TcmTemplateTitle("AddAssets")]
public class AddAssets : TemplateBase
{
public override void Transform(Engine engine, Package package)
{
Initialize(engine, package);
var items = m_Package.GetEntries();
var dynamicbinaries = new Dictionary<string, string[]>();
foreach (var i in items)
{
Logger.Info(i.Key + ":" + i.Value);
if (i.Key != "GenerateDynamic") continue;
Logger.Info("Generate Dynamic parsing:");
var arr = i.Value.GetAsString();
var binaries = arr.Split(',');
dynamicbinaries.Add(binaries[0], binaries);
}
var allowedContentTypes = new Dictionary<ContentType, ImageFormat>()
{
{ContentType.Bmp, ImageFormat.Bmp},
{ContentType.Jpeg, ImageFormat.Jpeg},
{ContentType.Png, ImageFormat.Png},
{ContentType.Gif, ImageFormat.Gif}
};
foreach (var contentType in allowedContentTypes.Keys)
{
foreach (var item in package.GetAllByType(contentType))
{
if (dynamicbinaries.ContainsKey(item.Properties[Item.ItemPropertyTcmUri]))
{
InsertRelatedBinaries(item, allowedContentTypes[contentType], dynamicbinaries[item.Properties[Item.ItemPropertyTcmUri]]);
}
}
}
}
private void GenerateDeviceSpecificBinaries(Item item, ImageFormat imageFormat, string[] binary)
{
var mmc = new Component(new TcmUri(item.Properties[Item.ItemPropertyTcmUri]), m_Engine.GetSession());
var binaryContent = mmc.BinaryContent;
var binaryBytes = binaryContent.GetByteArray();
using (var bitmap = new Bitmap(new MemoryStream(binaryBytes)))
{
var tabPercentage = Int32.Parse(m_Package.GetValue("TabPercentage"));
var mobilePercentage = Int32.Parse(m_Package.GetValue("MobilePercentage"));
var resizedBitmap = ResizeBitmap(bitmap, tabPercentage);
AddBitmapAsBinary(item, imageFormat, mmc, binaryContent, resizedBitmap, "2", binary[2]);//Tablet Images
resizedBitmap = ResizeBitmap(bitmap, mobilePercentage);
AddBitmapAsBinary(item, imageFormat, mmc, binaryContent, resizedBitmap, "3", binary[1]); // Mobile Images
resizedBitmap.Dispose();
}
}
private void AddBitmapAsBinary(Item item, ImageFormat format, Component mmc, BinaryContent binaryContent, Bitmap resizedBitmap, string variant, string filename)
{
var resizedStream = new MemoryStream();
resizedBitmap.Save(resizedStream, format);
var binary = this.m_Engine.PublishingContext.RenderedItem.AddBinary(
resizedStream, filename, variant, mmc,
binaryContent.MultimediaType.MimeType);
resizedStream.Dispose();
}
private Bitmap ResizeBitmap(Bitmap sourceBitmap, int per)
{
var sourceWidth = sourceBitmap.Width;
var sourceHeight = sourceBitmap.Height;
float nPercentW = per;
float nPercentH = per;
var destWidth = (int)(sourceWidth * (nPercentW / 100));
var destHeight = (int)(sourceHeight * (nPercentH / 100));
var resultBitmap = new Bitmap(destWidth, destHeight);
var graphicsd = Graphics.FromImage(resultBitmap);
graphicsd.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicsd.DrawImage(sourceBitmap, 0, 0, destWidth, destHeight);
graphicsd.Dispose();
return resultBitmap;
}
}
}
Tridion CID Contextual Image delivery is a product from SDL which helps in transforming the images in various ways such as
- Resize with Cropping
- Resize without Cropping
- Trim image
- Change Image format
Please read this very good article for further explanation of this module. What Does Contextual Image Delivery Mean for SDL Tridion Images?