user13286
user13286

Reputation: 3085

Using 2 slightly rotated SVGs as a navigation background?

I am creating the nav menu for my website and what I would like to do is have the background be a combination of 2 rectangular SVGs, each slightly rotated off axis and overlaid. The edges would extend beyond the edges of the screen so that they cannot be seen. The SVGs should remain the same height(120px) at all breakpoints and the navigation should be centered vertically within the container(even though it will appear off center due to the rotation). My current attempt has the SVGs heights shrinking as I resize the browser window, additionally I am having some issues with the alignment. Is there a better way to accomplish this?

.hero-bg {
  height:20vh;
  min-height:200px;
  max-height:350px;
  width:100%;
  background:url('http://placehold.it/1920x1080');
  background-size:cover;
}
.navigation {
	position:relative;
  height:120px;
  overflow:hidden;
}
.nav-bg-1 {
  fill:red;
}
.nav-bg-2 {
  fill:black;
}
.navigation svg {
	position:absolute;
	top:-10px;
	width:110%;
	left:-5%;
}
.navigation ul {
  list-style-type:none;
  padding:0;
  margin:0;
  position:absolute;
  top:50%;
  transform:translateY(-50%);
}
  .navigation ul > li {
    display:inline-block;
  }
    .navigation ul > li > a{
      color:#fff;
      text-transform:uppercase;
      text-decoration:none;
    }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" rel="stylesheet"/>
<section id="hero">
  <div class="hero-bg"></div>
  <div class="navigation">
      <svg viewBox="0 0 2027.79 155.34">
          <rect class="nav-bg-1" x="953.89" y="-935.33" width="120" height="2026" transform="translate(918.54 1090.05) rotate(-89)"/>
          <rect class="nav-bg-2" x="0.89" y="14.67" width="2026" height="120" transform="translate(-0.32 4.42) rotate(-0.25)"/>
      </svg>
      <div class="container">
          <div class="row">
              <div class="col-sm-4 hidden-xs">
                <!-- LOGO -->
              </div>
              <div class="col-sm-8">
                  <ul>
                      <li><a href="#">Home</a></li>
                      <li><a href="#">About</a></li>
                      <li><a href="#">Products</a></li>
                      <li><a href="#">Contact</a></li>
                  </ul>
              </div>
          </div>
      </div>
  </div>
</section>

Once I am able to accomplish these background bars, my plan is to animate them and slightly change the shape(make them not perfect rectangles), as the user scrolls, using MorphSVG. Because of this, the solution must use SVG in place of alternate solutions.

Here's a mockup of my desired result. The nav will be within a container, but the red/black bars should extend to the edge of the screen at any screen size:

enter image description here

Upvotes: 5

Views: 193

Answers (2)

f-spin
f-spin

Reputation: 161

If I understood good, in your case I would put both svg-bars independently. Maybe, grouped in a div.

(In the next snippet you'll still need to add some media queries to position the ul in the middle of the black bar, and the whole .navigation element. But I think you'll get the idea)

.hero {
  position: relative;
}
.hero-bg {
  height:20vh;
  min-height:200px;
  max-height:350px;
  width:100%;
  background:url('http://placehold.it/1920x1080');
  background-size:cover;
  z-index: -1;
  position: absolute;
}

.navigation {
  position:relative;
  width: 100vw;
  min-height: auto;
  height: auto;
  overflow:hidden;
  padding-top: 185px;
}

.svg-wrapper {
  position: absolute;
  width: 100%;
  height: 100%;
}

.nav-bg-1 {
  width: 105vw;
  position: absolute;
  z-index: -1;
  height: 50px;
  height: auto;
  left:-1em;
}

.nav-bg-rect-1 {
  fill: red
}

.nav-bg-rect-2 {
  fill: black;
}

.navigation ul {
  list-style-type:none;
  padding:0;
  margin:0;
  position:relative;
  padding: .6rem 1rem 1rem;
  height: 100%;
  width: 100%;
  transform: rotate(-1.01deg);
}

.navigation ul > li {
  display:inline-block;
}

.navigation ul > li > a{
  color:white;
  display: block;
  //padding: 2rem 1rem;
  text-transform:uppercase;
  text-decoration:none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css" rel="stylesheet"/>

<section id="hero" class="hero">
  <div class="hero-bg"></div>
  <div class="navigation">
    
    <div class="svg-wrapper">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1117.79 73" class="nav-bg-1">
        <defs></defs><title>rectred</title><g id="Laag_2" data-name="Laag 2"><g id="Laag_1-2" data-name="Laag 1"><rect class="nav-bg-rect-1" x="534.9" y="-522" width="48" height="1117" transform="matrix(0.02, -1, 1, 0.02, 509.89, 594.44)"/></g></g>
      </svg>
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1117.8 79.83" class="nav-bg-1">
        <title>rectblack</title><g id="Laag_2" data-name="Laag 2"><g id="Laag_1-2" data-name="Laag 1"><rect class="nav-bg-rect-2" x="0.4" y="7.92" width="1117" height="64" transform="translate(-0.51 7.93) rotate(-0.81)"/></g></g>
      </svg>
    </div>
    
    <div class="container">
          <div class="row">
              <div class="col-sm-4 hidden-xs">
                <!-- LOGO -->
              </div>
              <div class="col-sm-8">
                  <ul class="nav-bar">
                      <li><a href="#">Home</a></li>
                      <li><a href="#">About</a></li>
                      <li><a href="#">Products</a></li>
                      <li><a href="#">Contact</a></li>
                  </ul>
              </div>
          </div>
      </div>
  </div>
</section>

I think it's easy to read/work with two separate svg elements. In this case wrapped in a div. Positioned absolute behind you nav-list.

If I'm seeing right, your Menu has a slightly rotation (as the black bar?). So, I assume you will not transform this bar. Otherwise, I don't see what will happend with your Menu.

If this is not what you are looking for, could you explain, more in detail what kind of transformation you'll add to this bar(s)?

Just in case the codepen where I worked on it: https://codepen.io/fspin/pen/YYJyNY . (In the snippet there is a funny scroll!)


Update: I was thinking further. This may also be something in the right direction: https://codepen.io/fspin/pen/zpmdOd

There are a few things you will have to consider, I guess:

  1. In order to let the svg's flow out of the viewport, you would use vw and vh as units, and your container would have the property overflow hidden.
  2. In order to keep track of the position of your black bar, maybe you will have to put it just within the container. Which will gave another problem: it will not bleed out of the viewport. So, maybe with two svgs? One within the container, and one (the real one) within the svg's wrapper?

Maybe I'm overthinking this, but I like the challenge. Would love to hear more about if I'm thinking in the right direction.

Disclaimer: I'm not an expert on SVG's, nor on CSS, but I think I understand enough to try to solve this in a not too-hacky way.

Upvotes: 1

Temani Afif
Temani Afif

Reputation: 274384

I would probably go with pseudo element and skew transformation like this:

.navigation {
  display: flex;
  justify-content:center;
  margin-top:50px;
  height:80px;
  padding:30px 0;
  position:relative;
  margin-bottom:50px;
}
.navigation:before {
  content:"";
  position:absolute;
  right:0;
  left:0;
  top:10px;
  bottom:0;
  background:#000;
  transform:skewY(-3deg);
  z-index:2;
}
.navigation:after {
  content:"";
  position:absolute;
  right:0;
  left:0;
  top:10px;
  bottom:0;
  background:red;
  transform:skewY(3deg);
  z-index:1;
}
.navigation ul {
 position:relative;
 z-index:3;
}

.navigation ul>li {
  display: inline-block;
}

.navigation ul>li>a {
  color: #fff;
  text-transform: uppercase;
  text-decoration: none;
}
<div class="navigation">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Products</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</div>

Update

Since the solution should be using SVG, here is a solution that involve some js. The idea is to create what I have done previously using skew and svg but with a fixed width. Then I simply use the JS code to scale on widow resize so it remains full width:

$('.back-nav').css('transform', 'scaleX(' + $('.navigation').width() / 500 + ')');
$(window).resize(function() {
  $('.back-nav').css('transform', 'scaleX(' + $('.navigation').width() / 500 + ')');
});
body {
  margin: 0;
}

.navigation {
  display: flex;
  justify-content: center;
  margin-top: 50px;
  height: 80px;
  width: 100%;
  padding: 30px 0;
  position: relative;
  margin-bottom: 50px;
}

.back-nav {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: left;
}

.navigation ul {
  position: relative;
  z-index: 3;
}

.navigation ul>li {
  display: inline-block;
}

.navigation ul>li>a {
  color: #fff;
  text-transform: uppercase;
  text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navigation">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Products</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
  <svg class="back-nav" width="500" height="200" xmlns="http://www.w3.org/2000/svg">
  <rect x="0" y="20" width="500" fill="red" height="120" transform="skewY(3)"/>
  <rect x="0" y="50" width="500" height="120" transform="skewY(-3)"/>
</svg>
</div>

Another idea using background and without any JS (but you won't be able to apply morphing on it as it's a background)

body {
 margin:0;
}
.navigation {
  display: flex;
  justify-content:center;
  margin-top:50px;
  height:120px;
  width:100%;
  position:relative;
  margin-bottom:50px;
  background-image: url('data:image/svg+xml;charset=UTF-8,<svg version="1.1"  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" preserveAspectRatio="none" viewBox="0 0 25.1 30" style="enable-background:new 0 0 25.1 30;" xml:space="preserve"><polygon points="25,0 25,20 0,25 0,5" fill="red"/><polygon points="25,5 25,25 0,20 0,0" fill="black"/></svg>');
  background-size:100%;
}

.navigation ul {
 position:relative;
 z-index:3;
}

.navigation ul>li {
  display: inline-block;
}

.navigation ul>li>a {
  color: #fff;
  text-transform: uppercase;
  text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navigation">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Products</a></li>
    <li><a href="#">Contact</a></li>
  </ul>

</div>

Upvotes: 1

Related Questions