I'm displaying this component in an NgbModal:
<div id="gallerypopup">
<div id="main-image">
<lib-ngx-image-zoom id="zoomer"
[thumbImage]="item.thumbnailUrls[selectedIndex]"
[fullImage]="item.imageUrls[selectedIndex]"
zoomMode="click"
></lib-ngx-image-zoom>
</div>
<cdk-virtual-scroll-viewport orientation="horizontal" itemSize="400" minBufferPx="400" maxBufferPx="400" class="viewport">
<span *cdkVirtualFor="let thumbnail of item.thumbnailUrls; let index = index;" class="thumbcell">
<img [src]="thumbnail" height="300" (click)="selectImage(index)" /
</span>
</cdk-virtual-scroll-viewport>
</div>
with the following CSS:
#gallerypopup {
height: 75%;
width: 75%;
}
.thumbcell {
height: 300px;
width: 400px;
background-color: #dddddd;
margin: 0;
padding: 0;
cursor: pointer;
}
.viewport {
height: 300px;
}
.cdk-virtual-scroll-content-wrapper {
display: flex;
flex-direction: row;
}
.ngxImageZoomFullContainer {
cursor: zoom-out;
}
.ngxImageZoomThumbnail {
cursor: zoom-in;
}
But even though the scrolling viewport is set to horizontal orientation, the thumbnails still appear stacked vertically. How do I fix this? I suspect the problem is that the scrollable area is being incorrectly constrained to fit its width inside the width of the modal popup (which for some reason isn't 75% of the browser window, despite the first CSS rule).
Did you tried the following in order to display the elements horizontally?
.cdk-virtual-scroll-content-wrapper .viewport {
display: flex;
flex-direction: row;
}
Thing is .viewport children layout is still vertical.
Solution :
.viewport .cdk-virtual-scroll-content-wrapper {
display: flex;
flex-direction: row;
}
here is stackblatz this is example from angular material doc and i have modified it.
When I use overflow: hidden, top and bottom margins appear around these containers. I really don't understand why this should be. I'm looking for an explanation to help me understand CSS better.
Here is the code:
CSS CODE:
#container {
border: 2px solid black;
overflow: auto;
}
.field {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
display: inline-block;
padding: 0 5px;
border: 5px solid #FC0;
line-height: 1.5em;
overflow: hidden;
}
.w50 {
width: 50%;
}
.w100 {
width: 100%;
}
HTML CODE:
<div class="w50" id="container">
<div class="field w50">
<input type="text" size="100" value="input field that overflows #######################################">
</div>
<div class="field w50">content</div>
<div class="field w100">content</div>
</div>
If I don't use overflow: hidden, the container has no top and bottom margins, but I do have overflow issues.
http://jsfiddle.net/8ErHQ/2/
If I use overflow: hidden, the container (apparently) has top and bottom margins, but my overflow issues go away.
http://jsfiddle.net/8ErHQ/1/
Is there a way to use overflow: hidden and avoid this extra white space?
The mysterious whitespace you're seeing is because you made the divs inline-block, and inline elements are adjusted to text baseline, leaving room for descenders (letters that "hang low") like "j" and "g".
You can avoid the issue by setting a vertical-align value to something other than baseline (which is the default), like middle:
.field {
vertical-align: middle;
}
http://jsfiddle.net/8ErHQ/3/
...or just avoid using inline-block (float: left; instead, for instance)
For more information, you can check out https://developer.mozilla.org/en/docs/Images,_Tables,_and_Mysterious_Gaps
There is one other option you can do. Using the one without overflow: hidden; you can use this approach to fix your overflow issue.
Set your css to this.
.field input {
width: 100%;
}
And change your input field to this.
<input type="text" size="auto" value="input field that overflows #######################################"> //Size was changed to AUTO
Here is what you get.
http://jsfiddle.net/cornelas/8ErHQ/5/
Put a margin value in your .w50 and .w100 statement.There might be other fixes, but that's the fastest I could think of.
.w50 { margin: 0 0 -7px 0; width: 50%; }
.w100 { margin: 0 0 -4px 0; width: 100%; }
I am creating a custom pie chart using jqPlot's PieRenderer. My only problem is that I can either show the label or the percentage on the dataLabels. I want to do a mix and show both like <label>\n<percentage>. Explanation:
By setting this.dataLabels = 'percent', I can do this:
By setting this.dataLabels = 'label', I can do this:
I want to do this:
Do you have any ideas?
According to the source code, dataLabels doesn't support rendering label together with percent at the same time.
I think you can easily create a list of labels using JavaScript and make sure you use <br/> instead of \n if you want to render 2 lines for each part.
#sza's solution is tidier, so I will have to accept it. I wanted to post my own though, because it is easier and it may help someone.
What I did is, put two pieCharts on each other, where the first one is visible and has the percentage values and the second one has no fill and is invisible except for the labels.
My XHTML code:
<p:pieChart value="#{chartBean.pieModel}" legendPosition="" fill="true" showDataLabels="true"
title="MyPieChart" style="width:100%; height:350px" sliceMargin="2"
diameter="300" dataFormat="percent" shadow="false" extender="pieChartExtender"
seriesColors="7eb75b,c2715e,6367c2,9b6ece,5cc2c1,c0c216" styleClass="mainPieChart" />
<p:pieChart value="#{chartBean.pieModel}" legendPosition="" fill="false" showDataLabels="true"
title="MyPieChart" style="width:100%; height:350px" sliceMargin="2"
diameter="300" dataFormat="label" shadow="false" extender="pieChartLabelExtender"
seriesColors="7eb75b,c2715e,6367c2,9b6ece,5cc2c1,c0c216" styleClass="pieLabels" />
extender.js:
function pieChartExtender() {
this.cfg.seriesDefaults.rendererOptions.dataLabelFormatString = '%#.2f%%';
this.cfg.seriesDefaults.rendererOptions.dataLabelThreshold = 5;
this.cfg.seriesDefaults.rendererOptions.dataLabelPositionFactor = 0.8;
this.cfg.seriesDefaults.rendererOptions.startAngle = -90;
}
function pieChartLabelExtender() {
this.cfg.seriesDefaults.rendererOptions.dataLabelThreshold = 5;
this.cfg.seriesDefaults.rendererOptions.dataLabelPositionFactor = 0.8;
this.cfg.seriesDefaults.rendererOptions.startAngle = -90;
}
CSS file:
.chartContainer {
position:relative;
margin: 0 auto;
top: 10px;
width: 350px;
height: 350px;
}
.chartLegend {
border: 1px solid #d7d7d8;
margin: 40px 40px;
width: 80%;
}
.pieExtra {
position:absolute;
left: 17px;
top: 13.5px;
}
.pieLabels { position:absolute !important; }
.mainPieChart { position:absolute !important; }
.jqplot-title { display:none !important; }
.jqplot-grid-canvas { display:none !important; }
.jqplot-series-shadowCanvas { display:none !important; }
.mainPieChart .jqplot-event-canvas { z-index: 10 !important; }
.jqplot-data-label { color: #fff; font-weight: bold; font-size: 14px; }
.pieLabels .jqplot-data-label { margin-top: -9px !important; }
.mainPieChart .jqplot-data-label { margin-top: 8px !important; }
.pieLabels .jqplot-series-canvas { display:none !important; }
Notice that:
both pieCharts (called pieLabels and mainPieChart) are absolutely positioned, in order to be placed on each other
jqplot-data-label of pieLabels is placed 9px above and jqplot-data-label of mainPieChart is placed 8px below to create the label-percentage label
jqplot-series-canvas for pieLabels is not displayed, in order to make it invisible.
In my kendo mobile app I have some listviews that require more than one action. I need something like what is show in the Link Items & Detail Buttons demo but more flexible. In my case, I need to cover the following scenarios (all sections clickable):
[icon][text of the item]
[text of the item][icon]
[icon][text of the item][icon]
...where [icon] is some font icon.
I've started on a solution but before I go any further, I want some feedback to make sure I am not overlooking a better approach or something already built into Kendo.
Each "part" of the <LI> needs to perform a distinct action when clicked. To handle this, I have a click binding on the <UL>. I also have a data-command-name attribute on each element in the <LI> template so that I know what the user tapped/clicked.
I have put together a fiddle but jsFiddle is reformatting the HTML part when it loads (I think because of the template script tags). Once you load the fiddle please replace the HTML with the following to get it working:
HTML
<div id="itemsView" data-role="view" data-model="vm">
The red, silver and blue sections along with the X & Y are not part of the design, they are there just to make my intent more obvious.
<ul data-role="listview" data-bind="source: items, click: clickHandler"
data-template="itemsTemplate"></ul>
<script id="itemsTemplate" type="text/x-kendo-template">
<div class = "left-column" data-command-name="left (red)" > X </div>
<div class="right-column" data-command-name="right (blue)">Y</div >
<div class = "content-column" data-command-name="content (silver)"> #=Name# </div>
</script>
</div>
CSS
div.left-column {
float: left;
width: 25px;
margin-top: -5px;
padding-top: 5px;
margin-left: -5px;
padding-left: 5px;
cursor: default;
background-color: red;
}
.content-column {
margin-top: -5px;
margin-left: 25px;
margin-bottom: 0;
margin-right: 25px;
padding-top: 5px;
cursor: default;
background-color: silver;
}
.right-column {
float: right;
width: 25px;
margin-top: -5px;
padding-top: 5px;
cursor: default;
background-color: blue;
}
JavaScript
var vm = kendo.observable({
items: [{
Selected: false,
Name: "Item1"
}, {
Selected: false,
Name: "Item2"
}, {
Selected: false,
Name: "Item2"
}],
clickHandler: function (e) {
var cmd = e.target.context.attributes["data-command-name"]
if (cmd) {
alert(cmd.value);
}
},
});
kendoApp = new kendo.mobile.Application(document.body, {
transition: "slide",
platform: 'android'
});
Here is the fiddle: http://jsfiddle.net/8Kydw/
So to summarize my questions:
1) Is there a better/built-in way of doing this?
2) If not, any tips on the CSS? For instance, why in Android is the height of the list items smaller than prior to my customization?
1) I think the strategy that you are using is completely fine and acceptable for Kendo UI Mobile.
2) Kendo UI Mobile applies some pretty specific styling in the way of line-height and a few other items that will affect how the list item is displayed if you then customize margin or padding with your own CSS. I wouldn't worry too much about it though.
I need to make this image stretch to the maximum size possible without overflowing it's <div> or skewing the image.
I can't predict the aspect-ratio of the image, so there's no way to know whether to use:
<img src="url" style="width: 100%;">
or
<img src="url" style="height: 100%;">
I can't use both (i.e. style="width: 100%; height: 100%;") because that will stretch the image to fit the <div>.
The <div> has a size set by percentage of the screen, which is also unpredictable.
Update 2016:
Modern browser behave much better. All you should need to do is to set the image width to 100% (demo)
.container img {
width: 100%;
}
Since you don't know the aspect ratio, you'll have to use some scripting. Here is how I would do it with jQuery (demo):
CSS
.container {
width: 40%;
height: 40%;
background: #444;
margin: 0 auto;
}
.container img.wide {
max-width: 100%;
max-height: 100%;
height: auto;
}
.container img.tall {
max-height: 100%;
max-width: 100%;
width: auto;
}
HTML
<div class="container">
<img src="http://i48.tinypic.com/wrltuc.jpg" />
</div>
<br />
<br />
<div class="container">
<img src="http://i47.tinypic.com/i1bek8.jpg" />
</div>
Script
$(window).load(function(){
$('.container').find('img').each(function(){
var imgClass = (this.width/this.height > 1) ? 'wide' : 'tall';
$(this).addClass(imgClass);
})
})
There is a much easier way to do this using only CSS and HTML:
HTML:
<div
class="fill"
style="background-image: url('path/to/image.jpg');">
</div>
CSS:
.fill {
background-size: cover;
background-position: center;
width: 100%;
height: 100%;
}
This will place your image as the background, and stretch it to fit the div size without distortion.
Not a perfect solution, but this CSS might help. The zoom is what makes this code work, and the factor should theoretically be infinite to work ideally for small images - but 2, 4, or 8 works fine in most cases.
#myImage {
zoom: 2; //increase if you have very small images
display: block;
margin: auto;
height: auto;
max-height: 100%;
width: auto;
max-width: 100%;
}
If you're able to set the image as a background-image then you can do something like this, which will crop the image without stretching it:
<div style="background-image: url(...); background-size: cover; width: 100%; height: 100%;"></div>
If you need to stick with an <img> tag, then as of 2019, you can now use the object-fit css property that accepts the following values:
fill | contain | cover | none | scale-down
See https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
As an example, you could have a container that holds an image:
<div class="container">
<img src="" class="container_img" />
</div>
.container {
height: 50px;
width: 50%;
}
.container_img {
height: 100%;
width: 100%;
object-fit: cover;
}
If you can, use background images and set background-size: cover. This will make the background cover the whole element.
CSS
div {
background-image: url(path/to/your/image.png);
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: cover;
}
If you're stuck with using inline images there are a few options. First, there is
object-fit
This property acts on images, videos and other objects similar to background-size: cover.
CSS
img {
object-fit: cover;
}
Sadly, browser support is not that great with IE up to version 11 not supporting it at all. The next option uses jQuery
CSS + jQuery
HTML
<div>
<img src="image.png" class="cover-image">
</div>
CSS
div {
height: 8em;
width: 15em;
}
Custom jQuery plugin
(function ($) {
$.fn.coverImage = function(contain) {
this.each(function() {
var $this = $(this),
src = $this.get(0).src,
$wrapper = $this.parent();
if (contain) {
$wrapper.css({
'background': 'url(' + src + ') 50% 50%/contain no-repeat'
});
} else {
$wrapper.css({
'background': 'url(' + src + ') 50% 50%/cover no-repeat'
});
}
$this.remove();
});
return this;
};
})(jQuery);
Use the plugin like this
jQuery('.cover-image').coverImage();
It will take an image, set it as a background image on the image's wrapper element and remove the img tag from the document. Lastly you could use
Pure CSS
You might use this as a fallback. The image will scale up to cover it's container but it won't scale down.
CSS
div {
height: 8em;
width: 15em;
overflow: hidden;
}
div img {
min-height: 100%;
min-width: 100%;
width: auto;
height: auto;
max-width: none;
max-height: none;
display: block;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Hope this might help somebody, happy coding!
Thanks to CSS3
img
{
object-fit: contain;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
IE and EDGE as always outsiders:
http://caniuse.com/#feat=object-fit
That's impossible with just HTML and CSS, or at least wildly exotic and complicated. If you're willing to throw some javascript in, here's a solution using jQuery:
$(function() {
$(window).resize(function() {
var $i = $('img#image_to_resize');
var $c = $img.parent();
var i_ar = $i.width() / $i.height(), c_ar = $c.width() / $c.height();
$i.width(i_ar > c_ar ? $c.width() : $c.height() * (i_ar));
});
$(window).resize();
});
That will resize the image so that it will always fit inside the parent element, regardless of it's size. And as it's binded to the $(window).resize() event, when user resizes the window, the image will adjust.
This does not try to center the image in the container, that would be possible but I guess that's not what you're after.
You can use object-fit: cover; on the parent div.
https://css-tricks.com/almanac/properties/o/object-fit/
Set width and height of the outer container div. Then use below styling on img:
.container img{
width:100%;
height:auto;
max-height:100%;
}
This will help you to keep an aspect ratio of your img
If you want to set a max width or height (so that it will not be very large) while keeping the images aspect-ratio, you can do this:
img{
object-fit: contain;
max-height: 70px;
}
I came across this question searching for a simular problem. I'm making a webpage with responsive design and the width of elements placed on the page is set to a percent of the screen width. The height is set with a vw value.
Since I'm adding posts with PHP and a database backend, pure CSS was out of the question. I did however find the jQuery/javascript solution a bit troblesome, so I came up with a neat (so I think myself at least) solution.
HTML (or php)
div.imgfill {
float: left;
position: relative;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: cover;
width: 33.333%;
height: 18vw;
border: 1px solid black; /*frame of the image*/
margin: -1px;
}
<div class="imgfill" style="background-image:url(source/image.jpg);">
This might be some info
</div>
<div class="imgfill" style="background-image:url(source/image2.jpg);">
This might be some info
</div>
<div class="imgfill" style="background-image:url(source/image3.jpg);">
This might be some info
</div>
By using style="" it's posible to have PHP update my page dynamically and the CSS-styling together with style="" will end up in a perfectly covered image, scaled to cover the dynamic div-tag.
To make this image stretch to the maximum size possible without overflowing it's or skewing the image.
Apply...
img {
object-fit: cover;
height: -webkit-fill-available;
}
styles to the image.
Using this method you can fill in your div with the image varying ratio of divs and images.
jQuery:
$(window).load(function(){
$('body').find(.fillme).each(function(){
var fillmeval = $(this).width()/$(this).height();
var imgval = $this.children('img').width()/$this.children('img').height();
var imgClass;
if(imgval > fillmeval){
imgClass = "stretchy";
}else{
imgClass = "stretchx";
}
$(this).children('img').addClass(imgClass);
});
});
HTML:
<div class="fillme">
<img src="../images/myimg.jpg" />
</div>
CSS:
.fillme{
overflow:hidden;
}
.fillme img.stretchx{
height:auto;
width:100%;
}
.fillme img.stretchy{
height:100%;
width:auto;
}
This did the trick for me
div img {
width: 100%;
min-height: 500px;
width: 100vw;
height: 100vh;
object-fit: cover;
}
if you working with IMG tag, it's easy.
I made this:
<style>
#pic{
height: 400px;
width: 400px;
}
#pic img{
height: 225px;
position: relative;
margin: 0 auto;
}
</style>
<div id="pic"><img src="images/menu.png"></div>
$(document).ready(function(){
$('#pic img').attr({ 'style':'height:25%; display:none; left:100px; top:100px;' })
)}
but i didn't find how to make it work with #pic { background:url(img/menu.png)}
Enyone?
Thanks
I had similar issue. I resolved it with just CSS.
Basically Object-fit: cover helps you achieve the task of maintaining the aspect ratio while positioning an image inside a div.
But the problem was Object-fit: cover was not working in IE and it was taking 100% width and 100% height and aspect ratio was distorted. In other words image zooming effect wasn't there which I was seeing in chrome.
The approach I took was to position the image inside the container with absolute and then place it right at the centre using the combination:
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
Once it is in the centre, I give to the image,
// For vertical blocks (i.e., where height is greater than width)
height: 100%;
width: auto;
// For Horizontal blocks (i.e., where width is greater than height)
height: auto;
width: 100%;
This makes the image get the effect of Object-fit:cover.
Here is a demonstration of the above logic.
https://jsfiddle.net/furqan_694/s3xLe1gp/
This logic works in all browsers.
HTML:
<style>
#foo, #bar{
width: 50px; /* use any width or height */
height: 50px;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
}
</style>
<div id="foo" style="background-image: url('path/to/image1.png');">
<div id="bar" style="background-image: url('path/to/image2.png');">
JSFiddle
...And if you want to set or change the image (using #foo as an example):
jQuery:
$("#foo").css("background-image", "url('path/to/image.png')");
JavaScript:
document.getElementById("foo").style.backgroundImage = "url('path/to/image.png')";
Many of the solutions found here have some limitation: some not working in IE ( object-fit) or older browsers, other solutions do not scale up the images (only shrink it), many solution do not support resize of the window and many are not generic, either expect fix resolution or layout(portrait or landscape)
If using javascript and jquery is not a problem I have this solution based on the code of #Tatu Ulmanen. I fixed some issues, and added some code in case the image is loaded dinamically and not available at begining. Basically the idea is to have two different css rules and apply them when required: one when the limitation is the height, so we need to show black bars at the sides, and othe css rule when the limitation is the width, so we need to show black bars at the top/bottom.
function applyResizeCSS(){
var $i = $('img#imageToResize');
var $c = $i.parent();
var i_ar = Oriwidth / Oriheight, c_ar = $c.width() / $c.height();
if(i_ar > c_ar){
$i.css( "width","100%");
$i.css( "height","auto");
}else{
$i.css( "height","100%");
$i.css( "width","auto");
}
}
var Oriwidth,Oriheight;
$(function() {
$(window).resize(function() {
applyResizeCSS();
});
$("#slide").load(function(){
Oriwidth = this.width,
Oriheight = this.height;
applyResizeCSS();
});
$(window).resize();
});
For an HTML element like:
<img src="images/loading.gif" name="imageToResize" id="imageToResize"/>
try this
HTML:
<div class="container"></div>
CSS:
.container{
background-image: url("...");
background-size: 100%;
background-position: center;
}