Thank you in advance for your help.
I have spent a good deal of time scouring the web and this forum for a solution to having a diagonal angled bottom to my navigation buttons. Here is an example:
I want to avoid using images if possible. I'm wondering how to create a box like this in the example image for each navigation choice with CSS. This navigation code will make its way into a Wordpress install. I really appreciate the expertise. Thank you again!
So good-news, bad-news...
This can be most-of-the-way done using nothing but CSS.
For sufficiently-new browsers (ie: you don't require IE<=8 to maintain all styles that Chrome 42 has) this can be done without using extra DOM elements.
This can also be done using just CSS ...wait for it...
buuuut the CSS-only version can only make the angle a set width.
It can't make the angle stretch across an arbitrary width, so either the buttons have to be the same length, or the width/height of the angle has to be the same on all buttons (meaning part of the bottom will be flat, on longer buttons).
CSS-only Solution (good enough?)
nav {
background-color: green;
padding: 20px;
}
nav > button {
background-color: rgb(60, 60, 60);
color: rgb(120, 120, 120);
position: relative;
border-radius: none;
border: none;
padding: 20px;
}
nav > button:after {
content: "";
width: 0;
height: 0;
right: 0;
bottom: 0;
position: absolute;
border-left: 60px solid transparent;
border-bottom: 15px solid blue;
}
<nav >
<button >About</button>
<button >Bios</button>
</nav>
I made the colours obvious for a reason.
For the full experience of the cheat, I'll make the solution a little more obvious, by changing the colour of the left border:
Behind the Scenes Look
nav {
background-color: green;
padding: 20px;
}
nav > button {
background-color: rgb(60, 60, 60);
color: rgb(120, 120, 120);
position: relative;
border-radius: none;
border: none;
padding: 20px;
}
nav > button:after {
content: "";
width: 0;
height: 0;
right: 0;
bottom: 0;
position: absolute;
border-left: 60px solid red;
border-bottom: 15px solid blue;
}
<nav >
<button >About</button>
<button >Bios</button>
</nav>
As you can see, the triangle that I created using the border-bottom (in blue) and border-left (transparent) is just about perfect.
The width of the border-left determines the width of this effect, and the height of the border-bottom determines the height; it just happens that the left one is invisible.
If that blue were set to the same green as the <nav> itself, then it would look like a notch was missing from the button, rather than having a corner painted over.
If you wanted to make this ES6-8 friendly, you'd just add 1 div per button (after each button or whatever), and size that and use its borders.
Really, you'd need to add a div to contain the div and the button, as well (so the container was relatively positioned, the button took up 100% of its space, and the paint-chip was absolutely positioned inside).
If you don't care about old browsers getting the exact same view, you really don't need to do this to yourself.
That's most of the way solved...
If you can say "My theme's smallest button is 60px, so a 60px triangle is okay", then great. Change the colours and you're done.
If not, there's a little more you can do.
It's not ideal, and it's not as pretty as it could be (still prettier than a lot out there), but if you can use JS to do this, and you can guarantee that all of the buttons are going to be on the page before the code runs, and their widths won't change, you can do something like:
JS + CSS (good enough!)
(function () {
var nav;
var buttons;
var style;
var styleText;
function getElWidth (el) { return el.getBoundingClientRect().width; }
function borderLeftText (width, i) {
return ["nav > button:nth-child(", i + 1, "):after { border-left: ", width, "px solid transparent; }"].join("");
}
function getStyleEntries (els) {
return els.map(getElWidth).map(borderLeftText);
}
try {
nav = document.querySelector("nav");
buttons = [].slice.call(nav.querySelectorAll("button"));
style = document.createElement("style");
styleText = getStyleEntries(buttons).join("\n");
style.textContent = styleText;
document.head.appendChild(style);
}
catch (err) {
// because the same browsers that will blow up won't support the CSS anyway;
// don't fix it, just move on
// good code shouldn't do this, but that's another story
}
}());
nav {
background-color: green;
padding: 20px;
}
nav > button {
background-color: rgb(60, 60, 60);
color: rgb(120, 120, 120);
position: relative;
border-radius: none;
border: none;
padding: 20px;
}
nav > button:after {
content: "";
width: 0;
height: 0;
right: 0;
bottom: 0;
position: absolute;
border-left: 60px solid transparent;
border-bottom: 15px solid green;
}
<nav >
<button >About</button>
<button >Bios</button>
</nav>
Here I'm basically grabbing all buttons that exist at this time, and writing my own CSS file, full of
nav > button:nth-child(1):after { /*...*/ }
nav > button:nth-child(2):after { /*...*/ }
and then appending a <style> tag to the <head> with that text inside.
There will just be one rule inside each one of those selectors; the border-left width is going to be set to the actual width of the button, in pixels.
Terms and Conditions
Now you have exactly what you wanted, but it required JS and requires that the buttons be on the page before that code runs, and requires that the widths not change (through styling, or through media-queries, et cetera). If either of those things happens, and you want to keep the corners updated, that code needs to be run again.
And if that's the case, special care should be made to cache and reuse the style tag, so that you don't have 8 tags with the same rules, on the page.
Conclusion
If you're good with mostly-fine, go CSS-only.
If you're good with knowing that the fix doesn't have to respond in real-time, or be applied to more and more buttons that are dynamically added, go JS + CSS.
If neither of those is good enough, use an .svg or .png
Transform: skewY(deg);
will skew a div up like that, you might need to build it in layers though, and then skew the text -deg to unskew the text
Simple example:
https://jsfiddle.net/uex2umac/
.wrapper{
width:500px;
height:300px;
background-color:#000;
overflow:hidden;
}
.tobeskew{
width:280px;
height:220px;
margin-bottom:0px;
background-color:#f1f;
text-align:center;
transform:skewY(-15deg);
}
p{
transform:skewY(15deg);
line-height:220px;
font-size:40px;
color:#fff;
}
<Div class="wrapper">
<div class="tobeskew">
<p>Hello</p>
</div>
</div>
Here's a solution using SVG background images. Note that using SVG requires IE9+ though...
BODY
{
background-color: #333;
}
.button
{
float:left;
float: left;
font-family: sans-serif;
font-weight: bold;
font-size: 44px;
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 115' preserveAspectRatio='none'><polygon points='0 0 100 0 100 100 0 115' fill='%23282828'/></svg>");
background-size: 100% 100%;
color: #999;
height: 110px;
line-height: 96px;
padding: 0 50px;
margin-right: 10px;
}
.button.selected
{
color: #fbac31;
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 115' preserveAspectRatio='none'><polygon points='0 0 100 0 100 100 0 115' fill='black'/></svg>");
}
<div class="button">
<div>ABOUT</div>
</div>
<div class="button selected">
<div>BIOS</div>
</div>
Related
I'm making a portfolio page with html/css at the basic level
I made a button with an animation effect using pseudo-class: active.
Below is my html, css code.
div,
input,
textarea {
box-sizing: border-box;
}
body {
margin: 0;
}
html {
line-height: 1.15;
}
* {
margin: 0;
padding: 0;
}
.main-bg {
background: rgb(2, 0, 36);
background: linear-gradient(180deg, rgba(2, 0, 36, 1) 0%, rgba(172, 224, 255, 1) 0%, rgba(106, 166, 241, 1) 0%, rgba(73, 73, 182, 1) 100%);
width: 100%;
height: 1000px;
}
.main-introduction {
color: white;
width: 40%;
padding: 10px;
position: relative;
left: 100px;
top: 100px;
}
.main-introduction>h1,
p {
margin-bottom: 10px;
}
.showBtn {
/* margin-top: 10px; */
width: 110px;
padding: 15px;
border-radius: 15px;
background: rgb(98, 98, 98);
color: white;
border: none;
box-shadow: 3px 3px 3px black;
transition-duration: 0.3s;
cursor: pointer;
}
.showBtn:active {
margin-left: 5px;
margin-top: 5px;
box-shadow: none;
}
.phone {
width: 30%;
position: relative;
left: 1000px;
top: 2px;
}
.white-banner {
background: white;
text-align: center;
padding: 20px;
height: 200px;
}
.white-banner>h4,
p {
margin-bottom: 20px;
}
```
<body>
<div class="main-bg">
<div class="main-introduction">
<h1>Frontend Student Developer, <span style="font-size: larger; color: rgb(165, 255, 252);">Dan</span></h1>
<br>
<p>Always considering improvements, growing, code.</p>
<p>Recently fell in love with developing.</p>
<button class="showBtn">Show More</button>
</div>
<div>
<img src="img/phone.png" alt="phone" class="phone">
</div>
<div class="white-banner">
<h4>god tell us the reason youth is wasted on the young</h4>
<p>Lorem ipsum dolor sit amet consectetur elit.</p>
<button class="showBtn" style="width: 150px;">Show Portfolio</button>
</div>
</div>
</body>
When I cliked a button, as you saw, animation effect is happen by giving margin when I clicked(:active) btn.
But Phone image and white-banner also got animation effect!!
I thought about margin collapse. However, it was judged that it was not because the upper and lower borders were not overlapped.
Also I tried giving some additional margin. (Annotated code on .showBtn) But..
It didn't work, but rather the shadow effect turned strange. I also want to know why shadow effect turned strangely.
I don't know why this happened..
Problem : your 'html structure objects' interact with each others.
You can solve it too much ways with using css.
But you have to know this : 'The right way is only a few.'
This way is better for you : 'Learn more about CSS.'
For example :
Option 1 : Seperate your main objects divs and give they are some height and width.
Place they are right and left side.
// But you will have to give they are responsive behaviors.
// You will need some css experience.
Option 2 : Make your hero image 'absolute' not 'block'.
// And you will need for place it 'very well' some css knowledge like flex.
// learn 'flex'.
Option 3 : You can use your image like a background-image for your div.
// and make it contain, re-size and place it with some responsive behaviors.
// it will be never interaction with other html elements.
Option 4 : Use grids for seperate your html objects for not-interact with each others.
// learn grids.
// =============== best way. =============== //
if you don't want to save only today...
Examine other's similar html/css code examples.
Find similars but responsive ones.
// =============== best way. =============== //
When I created some code, I noticed something strange. The DOWNLOAD button touches the end of the left wall, there is no gap (500% zoom). But when I decrease the zoom from 500% to 250%, a piece of background appears (green color). Watch the video on which I show it. Below is the source code from the video. Is this a browser rendering bug or my code is bugged?
Windows 10, 10.0.18362, 64-bits
Google Chrome, 75.0.3770.100, 64-bits
video: https://youtu.be/uwAEixLBUeU
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>index</title>
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700&display=swap" rel="stylesheet">
<style>
html, body { margin: 0; border: 0; padding: 0; font-family: 'Montserrat', sans-serif; font-size: 1em; line-height: 1.2; color: #222; }
html { background: #bbb; }
body { width: 1000px; margin: 0 auto; background: #fff; }
a { text-decoration: none; }
.modelerInputReport {
overflow: hidden;
padding: 5px;
}
.modelerInputReportDiv {
float: right;
}
.modelerInputReportDiv span {
display: inline-block;
}
.modelerInputReportDiv button {
vertical-align: middle;
cursor: pointer;
font-weight: bold;
padding: 8px;
color: #fff;
border: 1px solid #ccc;
background: #0066cc;
margin-left: 5px;
}
.modelerInputReportDiv button:hover {
border: 1px solid #1B273F;
}
.modelerInputReportDiv button:active {
background: #cc7600;
border: 1px solid #402400;
box-shadow: inset 0 0 10px 2px #402400;
}
</style>
</head>
<body>
<div class="modelerInputReport">
<div class="modelerInputReportDiv">
<span id="modelerInputReportMsg">(generate to unlock) -</span>
<span>Report:</span>
<button id="modelerInputReportPrint" class="modelerInputReportPrint">PRINT</button>
<button id="modelerInputReportDownload" class="modelerInputReportDownload">DOWNLOAD</button>
</div>
</div>
</body>
</html>
In my experience this sort of thing is a rendering 'quirk', rather than a 'bug' per se. When you change the zoom level of a document, you're asking the browser to scale your '1px' border to a different number of pixels wide. Sometimes this doesn't equal a whole number of pixels, so the browser needs to do something to account for that. That something might be anti-aliasing, rounding widths to the nearest pixel, etc. This sort of thing needs to happen whenever you have anything that's not a whole number of pixels on screen. It's one of those things that happens at high-zoom levels, and in most cases it's not a big enough problem to worry about.
If it is a problem in your case, you can try doing things to minimise the effect, for example:
Use non-pixel measurements border: 0.1rem solid #CCC
Adjust the way the background is drawn: for example, include spacer elements between your buttons, and background color them, leaving the containing element background the same color as its border.
Experiment with small margin, transform or position adjustments (0.5px - 1px) to nudge the element slightly over the border.
These are all indirect ways of tricking the browser's renderer into doing something that's better for your specific case, and I'm not sure any of these will actually work. They might have undesirable side effects in other OS's and browsers, too.
TL:DR - It's the browser, and don't worry about it unless you really need to!
this is display:inline-block; issue because of inline-block use some spacing
Use float: left instead of display: inline-block,
Use this css
.modelerInputReportDiv span {
float:left;
}
.modelerInputReportDiv button {
float:left;
vertical-align: middle;
cursor: pointer;
font-weight: bold;
padding: 8px;
color: #fff;
border: 1px solid #ccc;
background: #0066cc;
margin-left: 5px;
}
Thanks for taking the time to read my post.
So I've started freelancing recently (CSS and HTML) and I've found my first difficulty.
Look at the green bar (Its a fixed div), its green for testing porpuses, but client wants it to be transparent when on top of this orange background...
...But switch to another color when on top of this white background (So the letters can be seen)
Is this possible to do with CSS? If so, how do I do it?
Thanks again!
Pure css does not currently have any amount of responsiveness to what is and is not onscreen. So, the short lame answer is "not with just css."
That being said, it's very easy to do this with js.
The event you'll be looking for is scroll event.
From there you can add/remove a class for styling.
Something like this:
// wait for document.addEventListener("DOMContentLoaded");
const myHeader = document.getElementById("MyHeader");
window.addEventListener("scroll", () => {
const scrollPos = window.scrollY;
if (scrollPos ... add your logic here) {
myHeader.classList.add("scrollIsThing"); // this is the css class you'll target
} else {
myHeader.classList.remove("scrollIsThing");
}
});
Sorry there's no good css way to do this.
It is "kind of" possible to do this just with css if you can accept some html markup duplication. You can split the fixed header into two layers, one for white text, one for background, and using z-index you can sandwich the content between these two header layers (in case of a colorful content), in which case only the white text would be visible, and position the white content below the header background. A sample of such behavior is shown below:
.header {
height: 50px;
background: transparent;
position: fixed;
top: 0;
width: 100%;
color: white;
font-family: sans;
text-align: center;
line-height: 50px;
z-index: 3;
}
.header.header-background {
background: teal;
z-index: 1;
}
.body1 {
height: 120vh;
background: orange;
z-index: 2;
position: relative;
}
.body2 {
height: 120vh;
background: #eee;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
<div class="header">
White text
</div>
<div class="body1"></div>
<div class="header header-background">
</div>
<div class="body2"></div>
I am trying to create a box that has a 'highlight' down the sides of it, and at the top.
The CSS for the box was pretty simple, however, now that I introduced this 'highlight' to the design, it has added another level of complexity to the CSS...
I have tried a lot of things, not sure if they will help but here is my most recent:
/* Define the Main Navigation Drop Downs */
#mn_navigation .dd {position:relative;width:226px;padding:29px 0 0;background:transparent url("//beta.example.co.uk/_images/_global/dd_handle.png") no-repeat;z-index:1000;}
#mn_navigation .dd nav {padding:30px 0;background:#3E5032 url("//beta.example.co.uk/_images/_global/dd_bg.png");border-radius:3px;}
#mn_navigation .dd nav a {font-family:Arial, Helvetica, sans-serif;font-size:12px;color:#fff !important;height:25px;line-height:25px;}
Please note I have posted the above to show that I have actually tried to sort this myself. The above code will probably not even help as a starting point as a restructure of the HTML may be necessary!
Here is the current HTML (probably needs to be restructured):
<div id="dd_foo" class="dd">
<nav>
LINK
</nav>
</div>
Here is a possible restructure (something like):
<div id="dd_foo" class="dd">
<div class="handle"><!-- Dropdown Handle --></div>
<nav>
LINK
</nav>
</div>
This is what I need the box to look like (notice the faint white border at the top and half way down the sides):
I have also included the box split into its separate elements (handle and background)
I think I can see how this can be done with clever overlaps and nested divs, but ideally I don't really want to resort to this... Can anybody suggest an alternative solution?
Simplest approach
You can try achieving this using a simple box shadow:
.plaque {
box-shadow: inset 0 1px 1px 0 rgba(255, 255, 255, 0.32);
/*...*/
}
An Example
Here's an example using 1 class and a div on jsbin.
Copy paste code
This code is only for modern browsers; it might cause ie < 9 and other non supporting browsers to explode.
.plaque:after {
top: -9px;
content: " ";
height: 11px;
width: 30px;
position: absolute;
pointer-events: none;
left: 50%;
margin-left: -15px;
display: block;
background-repeat: no-repeat;
}
.plaque {
width: 250px;
height: 100px;
display: block;
border: 0;
outline: 0;
padding: 12px 16px;
line-height: 1.4;
box-shadow: inset 0 1px 1px 0 rgba(255, 255, 255, 0.32);
border-radius: 5px;
border: 1px solid transparent;
font-family: sans-serif;
color: white;
font-size: 1.2em;
text-overflow: ellipsis;
position: relative;
top: 6px;
}
/* Use whatever background you want */
.plaque { background-color: green; }
.plaque:after { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAALCAYAAACZIGYHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAcJJREFUeNqMUktPU0EU/mZuL6Up1RCjC4oRau4t4FJ84EKID/ZAjI9/6Mo/4MadG5dqJGjBatpyuY+2UNreeXDOBE0MNHGSSWZyzvnOd77zicdbd+EVJKyxGPSHmC4XIYSAMQYCoJhn81wJKSnHWhR8D1oZl69yhamiD8GBSefpywc2XKzjy7fP+PDuk5iUJxnksvvkxX1buxkgThOEt5exvr1qJ+XKy5CfvXpow9oSsn6GdqeF40EPK+GKY/ZfTNa3Vm1AI6TdFAeNfQgp0CKgrJehVg1AGl5gJLTWfxGfv15zI3BBnB5CehJGG5Cw8EjY6tw8KjNXsfv9K96//SguMOERgoU6+ic9NH8eQClNGzDQBMLb4FU1fzdxFB+hev0WNnbu2X802TxnkGQJoriNymwZHrFgAbhdidbOK+YTxR0ojLEc3sHmm0dOI8Gq10n9OI1xGLVcMvuGGYyHOYqlKcfK9wvOF3/i12ZvoFK+gsavPUgGSLsJkm4En4xDTqMi45iUZqZdd34zJY7L8was2enoGMHCEmS3l6LxYx9qrJ2I7FTNelBxPlKuYDgYu9nzUe6cenoygqF/J2o7AmcCDACumSjtgWp8aAAAAABJRU5ErkJggg==); }
Problem
I am working on a project to theme a website, but I am not allowed to change the HTML or JavaScript. I can only update the CSS stylesheet and add/update images.
Requrements
I need to style a h3 tag to have an
underline/border after the content.
This h3 will be used multiple times
on the page, so the conent length can
vary
The solution needs to be
cross-browser (IE 6/7/8, FF 3, &
Safari)
Sample Code
<div class="a">
<div class="b"><!-- etc --></div>
<div class="c">
<h3>Sample Text To Have Line Afterwards</h3>
<ul><!-- etc --></ul>
<p class="d"><!-- etc --></p>
</div>
</div>
Sample Output
Sample Text to Have Line Afterwards ______________________________________
Another Example __________________________________________________________
And Yet Another Example __________________________________________________
Notes
I think #sample:after { content: "__________"; } option wouldn't work since that would only be the correct length for one of the tags
I tried a background-image, but if it gave me problems if I gave it one with a large width
Using text-indent didn't see to give me the effect I was looking for
I tried a combination of border-bottom and text-decoration: none, but that didn't seem to work either
Any ideas would be much appreciated!
This will work if class 'c' is always the parent of the h3...
.c {
position: relative;
margin-top: 25px;
border-top: 1px solid #000;
padding: 0px;
}
h3 {
font-size:20px;
margin-top: 0px;
position: absolute;
top: -18px;
background: #fff;
}
It lets the container have the border, then uses absolute positioning to move the h3 over it, and the background color lets it blot out the portion of c's border that it's covering.
try attaching a background image to class c of a repeating underline, then add a background color to the h3 to match the background of the container. I believe that you would have to float the h3 left in order to get the width to collapse. does that make sense?
.c {
background: #ffffff url(underline.gif) left 20px repeat-x;
}
.c h3 {
margin: 0;
padding: 0 0 2px 0;
float: left;
font-size: 20px;
background: #ffffff;
}
.c h3 { display: inline; background-color: white; margin: 0; padding: 0; line-height: 1em; }
.c ul { margin-top: -1px; border-top: 1px solid; padding-top: 1em; /* simulate margin with padding */ }
http://besh.dwich.cz/tmp/h3.html
H3 {
border: 1px solid red;
border-width: 0 0 1px 0;
text-indent: -60px;
}
You need to know the width of the text, but works pretty well.
The only solution I've imagined so far is to make a PNG or GIF image, with 1px height and a very large width (depends on your project, could be like 1x2000px), and do something like this:
h3#main-title { background: url(line.png) no-repeat bottom XYZem; }
where the XYZ you'd set manually, for each title, in 'em' units. But I can't figure out a 100% dynamic solution for this one, without using JS or adding extra markup.
this worked for me
div.c
{
background-image:url(line.gif);background-repeat:repeat-x;width:100%;height:20px;
}
div.c h3
{
height:20px;background-color:white;display:inline;
}
you make the div the width of your content
then you set the background of the h3 to the background of your page. this will then overlap the background imageof the full div. You might want to play with background positioning depending on your image
Can you pad content in the UL tags? If so, this might work:
h3 { display: inline; margin: 0; padding: 0 10px 0 0; float: left;}
ul { display: inline; border-bottom: 1px solid black; }
check source code of: http://nonlinear.cc/lab/friends/elijahmanor.html
then again i have NO IDEA how to control the end of the line.
Assuming that you're working with dynamic content, the best I could suggest is to accept graceful degradation and use a mix of great_llama and Bohdan Ganicky
Imagine:
A long title that will wrap to two lines___________________
and leave you like this in great_llama's solution
and nothing appearing at all with Bohdan Ganicky's solution if ul isn't immediate preceded by ul.
Solution:
.c h3 { display: inline; background-color: white; margin: 0; padding: 0; line-height: 1em; }
.c + * { margin-top: -1px; border-top: 1px solid; padding-top: 1em; /* simulate margin with padding */ }
We care about IE6, but accept that this is an aesthetic touch and IE6 users will not suffer. If you can't get the designer to accept this AND you can't alter the HTML, then do something else (before you find another job ;))
Here's a better answer:
.c {
background: url('line.png') repeat-x 0 20px;
}
H3 {
background-color: white;
display: inline;
position: relative;
top: 1px;
}
Use a small, 1px height, couple px wide image as your underline and occlude it with a background color on your H3.
h3:after {
content: '___________';
}