Stretch background image with border image - css

The following image represents the desired outcome.
Typically I'd apply such case using 3 divs:
<div class="holder">
<div class="edge left"></div>
<div class="content">background color or image stretched here</div>
<div class="edge right"></div>
</div>
This sounds like an overuse of semantics, so I decided to try using border-image, and this is the end result:
But, if I set a background color, it will act as a background for the borders too (can be solved using JPEG instead of PNG with a white background -but this isn't a solution-).
Any ideas or suggestions? Is the use of border-image recommended in the first place (any browser rendering variability?).
The image used and code are below:
<ul id="nav">
<li>Test data Test data Test Data</li>
</ul>
#nav {
border-width: 0px 38px;
border-image: url(images/nav-border.png) 0 50;
height: 30px;
}
https://jsfiddle.net/y7g7w1b3/

Solution 1: Using fill and stretch for border image
You can do this with border-image property itself by using the following settings:
The value fill for border-image-slice. (Make sure that slice is less than half the width of the original image). You can find more details about this option in MDN.
The value stretch for border-image-repeat.
This works in IE11, Edge, Firefox v45, Opera v36, Chrome v51 (dev-m).
#nav {
border-width: 0px 38px;
border-image: url(http://i.stack.imgur.com/5foMd.png);
border-image-width: 34px 98px;
border-image-slice: 17 48 fill;
border-image-repeat: stretch;
height: 30px;
}
#nav li {
line-height: 30px;
}
#nav li a {
color: white;
}
<ul id="nav">
<li>Test data Test data Test Data
</li>
</ul>
Solution 2: Using background color
But, if I set a background color, it will act as a background for the borders too
You can actually clip the background-color such that it doesn't cover the borders. This option can work as long as the shape's background is a solid color.
#nav {
border-width: 0px 38px;
border-image: url(http://i.stack.imgur.com/5foMd.png) 0 50;
background-color: rgb(34,34,34);
background-clip: padding-box;
height: 30px;
}
#nav li {
line-height: 30px;
}
#nav li a {
color: white;
}
<ul id="nav">
<li>Test data Test data Test Data
</li>
</ul>

I wouldn't use border image, instead I would use :before and :after. This creates 2 additional elements before and after your container.
Code below:
.container{
position: relative;
}
.container:before,
.container:after{
position: absolute;
top: 0;
bottom: 0;
content: "";
display: block;
width: 50px;
}
.container:before{ right:100%: }
.container:after{ left: 100%; }
This will create the before and after elements for your container on each side. Then you can style the two elements as required.

You can use a 1px background-image to act as your background-color (I used black in my example, embedded as base64) then combine background-size, background-repeat and background-position to achieve your goal:
Something like:
#nav {
background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=);
background-repeat: repeat-y;
background-size: 100%;
background-position: center center;
border-width: 0px 38px;
border-image: url(images/nav-border.png) 0 50;
}
See Fiddle

Related

CSS transform and fixed positioning in Safari

I'm having troubles with fixed positioning, css transformed container and Safari. I'm trying to display a dropdown list when I click an item, inside a modal. The modal bears a css transform. To make sure the dropdown list is always displayed over the modal, I position it as fixed (I calculate the left and top values using JS).
It works as expected in Chrome, Firefox and Opera, but Safari shows a strange behaviour. According to the W3C:
Any computed value other than none for the transform results in the
creation of both a stacking context and a containing block. The object
acts as a containing block for fixed positioned descendants.
So a fixed element inside a CSS transformed container should be positioned relatively to this container, instead of the viewport. But it seems that Safari does not behave like this. See this example :
$(document).ready(function() {
$(".show-liste").click(function() {
$(".liste").show();
});
});
.modale {
height: 50px;
overflow-y: scroll;
transform: translate(100px);
}
ul {
position: fixed;
left: 0px;
top: 0px;
}
/* --- Purely style related stuff ---- */
body {
font-size: 80%;
}
.modale {
position: absolute;
top: 50px;
padding: 60px;
background-color: white;
border: 1px solid #ccc;
box-shadow: 2px 2px 2px #ddd;
}
button {
width: 200px;
}
ul {
list-style-type: none;
margin-top: 0;
padding-left: 0;
width: 200px;
display: none;
box-shadow: 2px 2px 2px #ddd;
}
li {
background: white;
padding: 10px 20px;
border: 1px solid #eee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="modale">
<div class="row">
<div>
<button class="show-liste">Open dropdown</button>
<ul class="liste">
<li>Choice 1</li>
<li>Choice 2</li>
<li>Choice 3</li>
<li>Choice 4</li>
<li>Choice 5</li>
</ul>
</div>
</div>
</div>
Do you have any idea how to fix this ? Any polyfill, any way to get round this issue ? USing absolute positionning is the solution I'd like to avoid, as it would imply moving the list at the document's body level, and then handling it's creation / destruction, attached model (I'm using AngularJS), events, etc. That's really my last resort.
I believe you can get the desired cross-browser behavior by using position:absolute instead of position:fixed.

Perfectly overlapping round divs

I have a list which has round elements in it. They have a image in the background and on hover the other div is supposed to become visible as an overlay. It works so far, however there is still a visible border, indicating that the hovered div is not perfectly overlaying the other rounded element.
HTML:
<ul>
<li>
<div class="hover"></div>
</li>
<li>
<div class="hover"></div>
</li>
<li>
<div class="hover"></div>
</li>
</ul>
CSS:
ul {
margin: 0;
padding: 0;
list-style: none;
font-size: 0;
height: 140px;
}
li {
width: 140px;
height: 140px;
margin: 0;
padding: 0;
display: inline-block;
border-radius: 70px;
background: url(http://www.nationalflaggen.de/media/flags/flagge-thailand.gif);
}
.hover {
border-radius: 70px;
width: 140px;
height: 140px;
}
.hover:hover {
background-color: rgba(255,255,255,.9);
}
I added a fiddle since I really don't know how to make them perfectly overlapping.
Thanks for your help.
UPDATED THE FIDDLE:
http://jsfiddle.net/pL9Aa/1
Looks like a sub-pixel problem -- the browser does a bunch of math to determine the smoothness of a curve using square pixels. And sometimes it doesn't render how you might expect.
You can simply remove the border-radius rule from the :hover pseudo class if you are keeping it transparent.
.hover {
width: 140px;
height: 140px;
}
Fiddle
If it needs to be round, I would override your image using the same element, instead of a nested element, like so:
li:hover {
background: white;
}
Fiddle2
You could add:
li:hover {
background:none;
}
to ensure that the background on the li is gone.
It's weird though - does look like a rendering bug.
Assuming that you are going to have text or other content in the overlay, it's worth noting that setting the background to be slightly transparent (e.g. rgba(255,255,255,0.8)) makes the rendering error less noticeable.
Just change #hovers border-radius: 62px;
If your hover is only meant to cover the element, you do not need to put a border-radius on the hover element. Simply removing that line will resolve your issue:
.hover {
width: 140px;
height: 140px;
}
http://jsfiddle.net/pL9Aa/3/
If in the production envirionment you can actually use a background color, you could also use a box-shadow
demo: http://jsfiddle.net/j4NFB/
.hover:hover {
background-color: #FFF;
box-shadow: 0 0 0 1px #fff;
}

Why doesn't the margin property effect inline elements?

Trying to move some Nav Bar links around within a div, and they are not responding. Can anyone please offer any assistance on this? margin-top seems to be doing nothing. New to CSS.
CSS
#nav {
height: 70px;
vw: 100%;
background-color: hsla(0, 0%, 83%, .7);
margin-left: -10px;
margin-top: -16px;
margin-right: -10px;
border-bottom: 1px black solid;
}
li {
list-style-type: none;
display: inline;
font-family: Helvetica, sans-serif;
font-size: 20px;
padding-right: 20px;
color: hsl(0, 0%, 50%);
margin-top: 10px;
}
li:hover {
color: white;
}
HTML
<header>
<div id="nav">
<ul>
<li>About</li>
</ul>
</div>
<h1>Hi. This is my playground.</h1>
</header>
<div id="me">
<img src="dp.jpg">
</div>
The margin property doesn't affect inline elements, therefore it doesn't work.
Margin properties specify the width of the margin area of a box. The 'margin' shorthand property sets the margin for all four sides while the other margin properties only set their respective side. These properties apply to all elements, but vertical margins will not have any effect on non-replaced inline elements. http://www.w3.org/TR/CSS21/box.html#margin-properties
Also see this answer as to why dimensions cannot be set on inline elements.
To solve this, you can either change li to display:inline-block. (example) - it works.
Alternaetively, you could also float the li elements, having the same desired effect. (example)
In the #nav you have a typo:
vw: 100%;

CSS navigation with cut-out notch as marker

I know I have seen this somewhere before, but I am trying to create a black fixed navbar with a marker that is transparent cut-out triangle. I need help getting the triangle cut-out to be transparent to the background, so when you scroll the page, you can see through to the content beneath:
I have a standard list/anchor navigation with a javascript to move the .current class depending upon the page section:
<div class="navbar">
<ul>
<li class="current"><a>home</a></li>
<li><a>products</a></li>
<li><a>services</a></li>
<li><a>contact us</a></li>
</ul>
</div>
styled with the following CSS:
.navbar {
width: 100%;
position: fixed;
background: black;
float: left;
}
ul, li {
list-style: none;
margin: 0;
padding: 0;
float: left;
}
a {
padding: 10px 20px 20px;
}
.current a {
background: transparent url('../img/wedge-red.png') center bottom no-repeat;
}
The only way I can think to do it is to add extra divs on either side of the ul and assign the background to them, and then use a transparent png with a cutout as the background of the li a's.
Is there a way to do this without getting really ugly like that, and adding extra divs?
Try CSS pseudo elements!
Add 2 free DOM elements before and after an existing element in the DOM. Ideal in cases when you don't want to add stuff to your markup to satisfy styling needs.
CSS Markup
.item:before {
content:"";
display: inline-block;
width: 20px;
height: 20px;
background-color: silver;
}
.item:after {
content:"";
display: inline-block;
width: 20px;
height: 20px;
background-color: gray;
}
HTML
<div class="item">Content</div>
Check this JSFiddle for a demo.
Make sure you set content: "" and display:block in order to see them.
Here's what I ended up with -- extending the borders and cropping them with overflow: hidden; (a little hacky, but it works and doesn't add elements to the DOM):
.navbar {
width: 100%;
height: 60px;
position: fixed;
overflow: hidden;
}
ul {
border-left: solid black 2000px;
border-right: solid black 2000px;
position: absolute;
top: 0;
left: 50%;
margin-left: -2000px;
}
The above worked nicely for my purposes, and behaves in a responsive environment.
The other answer on this page, using :before and :after pseudo elements didn't work for my purposes. It ended up being too fussy, the pseudo elements wouldn't align properly, and kept wrapping to the next line when the browser window was resized. That solution as suggested works with fixed-width elements, not percentages as was specified in the original question.

css background image is being cut off

I have an unordered list and the background image is being cut off when trying to place it next to the text.
I'm using jquery to add the class to the anchor tag to display the image, and its working fine, the only problem is the image gets cut off. I've been playing around with the css, but can't seem to figure out how to make the image display properly...it seems like the < li > is hiding the image behind it somehow...can I place the image in front of the < li > to make it display...or am I missing something else?
Can someone help me? Thanks.
Here's the HTML:
<ul id="nav>
<li>
<a class="folder_closed">Item 1</a>
<div style="display:none">Content for item 1</div>
</li>
</ul>
Here's the CSS:
ul#nav{
margin-left:0;
margin-right:0;
padding-left:0px;
text-indent:15px;
}
#nav > li{
vertical-align: top;
text-align:left;
clear: both;
margin-left:0px;
margin-right:0px;
padding-right:0px;
padding-left:15px;
}
.folder_open{
position:relative;
background-image: url(../images/maximize.png);
background-repeat: no-repeat;
background-position: -5px 1px;
}
.folder_closed{
position:relative;
background-image: url(../images/minimize.png);
background-repeat: no-repeat;
background-position: -5px 1px;
}
This sounds like a line-height issue---just for experimentation try setting the LI "line-height: 40px;" and see if your image shows completely...
One of the things I do in this case is I use some absolute positioning. First to set it up you have to have your UL and LIs relatively-positioned:
<style type="text/css">
ul, li {
position: relative;
}
</style>
<ul>
<li> ... </li>
<li> ... </li>
<li> ... </li>
</ul>
Then add some padding to the left side of the LI:
<style type="text/css">
li {
padding-left: 30px;
}
</style>
In this case you're using an <A> anchor w/ some class styling. Break up the <A> into two As:
<li>
<a class="folder_icon folder_closed"></a>
<a class="folder_title">... your title ...</a>
... your other content ...
</li>
And then turn one of the As into blocked display:
<style type="text/css">
li .folder_icon {
position: absolute;
left: 0px;
top: 0px;
display: block;
width: 16px;
height: 16px;
}
li .folder_closed {
background-image: url("../images/minimize.png");
background-repeat: no-repeat;
background-position: -5px 1px;
}
</style>
How is that?
You need to add display:block and some dimensions (and perhaps some padding to make it look nice) to your A tag to ensure the element will be big enough to contain your background image.
You're better off transferring all of the styling to your A tag. Don't bother styling the LI tags at all (unless you need floats).
.folder_open{
vertical-align: top; <--- use padding to accomplish this instead
text-align:left; <-- this too
clear: both;
margin-left:0px;
margin-right:0px;
padding-right:0px;
padding-left:15px;
position:relative; <--- not needed.
background-image: url(../images/maximize.png);
background-repeat: no-repeat;
background-position: -5px 1px;
display:block;
height: ??px;
width: ??px
}
It looks like it might be your background position... if I understand it properly, the maximize image is disappearing, correct?
Also, one good practice, when specifying background images, I have found, is to explicitly set the background color to transparent.
.folder_closed {
background: transparent url(../images/maximize.png) no-repeat scroll -5px 1px;
}
add "line-height: ?px;" to the container style-sheet

Resources