Mike  Kozey

Mike Kozey

1661408541

Bloc_services: Package Has Implementations for Ease Of Stream Handling

bloc_services

A package which has useful implementations of streams for bloc considered with the clean architecture way and is fully tested

Features

  • Written for the usage with Clean Architecture
  • Provides Stream mixins when can be intergrated with blocs/cubits
  • Uses Either from dartz to get the proper stream data.

Getting Started

Add to the pubspec dependencies

dependencies:
  bloc_services: <latest-version>
  flutter_bloc: <latest-version>

Usage

Check the full example in the example directory on how to use it effectively with bloc.

class ExampleBloc
    extends Bloc<ExampleEvent, ExampleState>
    with
        MultipleStreamMixin{
  MultipleStreamExampleDartBloc() : super(MultipleStreamExampleInitial());

  @override
  Stream<MultipleStreamExampleState> mapEventToState(
    MultipleStreamExampleEvent event,
  ) async* {}

  @override
  Map<Object, StreamData<Object, Object>> get streams => {};

}

Mix your bloc with the MultipleStreamMixin when mixed it has an override called streams

It's a Map<Object, StreamData<Object, Object>> where your can pass a unique key (any object, check the example directory for a detailed implementation) and a StreamData which has a field stream

  • stream has the return Type of Either<L,R> where the L is considered as an error and the R is considered as a valid data
  • StreamData has 2 Type Parameters <L,R> these types will be used as the return type of the field stream
  • when ever a stream emits R of the either a function name onStreamData will be called which has 2 params one is the key which was given in the streams map in the override and the other is the data of the R;
  • onStreamError is called whenever the L of the either is called

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add bloc_services

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  bloc_services: ^0.0.6

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:bloc_services/bloc_services.dart';

example/lib/main.dart

import 'package:example/features/stream_bloc_example/page/stream_bloc_page.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const StreamBlocPage(),
    );
  }
}

Download Details:

Author: Afsal102
Source Code: https://github.com/Afsal102/bloc_services 
License: MIT license

#flutter #dart #bloc #services 

Bloc_services: Package Has Implementations for Ease Of Stream Handling

BioServices.jl: Julia interface to APIs for Various Bio-related

Description

BioServices provides an interface to APIs for various web services.

Installation

Install BioServices from the Julia REPL:

using Pkg
add("BioServices")

If you are interested in the cutting edge of the development, please check out the master branch to try new features before release.

Testing

BioServices is tested against Julia 0.7 and current 1.0 on Linux, OS X, and Windows.

PackageEvaluatorLatest Build Status

Questions?

If you have a question about contributing or using BioJulia software, come on over and chat to us on Discord, or you can try the Bio category of the Julia discourse site.

Download Details:

Author: BioJulia
Source Code: https://github.com/BioJulia/BioServices.jl 
License: View license

#julia #services 

BioServices.jl: Julia interface to APIs for Various Bio-related
Lawrence  Lesch

Lawrence Lesch

1659635940

A guideline of best practices that you can apply to your JavaScript

JavaScript Unit Testing Best Practices

This is a guideline of best practices that we can apply to our JavaScript project. Tests are code too. They should meet the same level of quality as the code being tested. They can be refactored as well to make them more maintainable and/or readable.

Follow conventions

A style guide is a set of standards that outline how code should be written and organized. Good projects have clear consistent coding conventions, with automated enforcement. The code conventions must be dynamic and adaptable for each team and project. It is up to each team to define its convention. We can follow the guides available in A guide to unit testing in JavaScript, Node.js & JavaScript Testing Best Practices and Frontend testing standards and style guidelines.

Follow Design Principles

The key to good unit testing is to write testable code. Applying simple design principles can help:

  • Use a good naming convention and comment the code;
  • Avoid code duplication;
  • Single responsibility: each object/function must focus on a single task;
  • Any given behaviour should be specified in one and only one test;
  • The execution/order of execution of one test cannot affect the others;
  • Minimize dependencies between components;
  • Use design patterns;
  • Avoid global mutable state.

Follow the Arrange-Act-Assert pattern

The Arrange-Act-Assert pattern (AAA) is abstraction for separating the different part of the tests. So, the Arrange section we only have code required to setup that specific test. Here objects would be created, mocks setup (if we are using one) and potentially expectations would be set. Then there is the Act, which should be the invocation of the method being tested. On Assert we would simply check whether the expectations were met. In the next example, these principles are applied in a Jasmine style.

describe('Array', () => {
  describe('.push(x)', () => {
    let initialArray;

    beforeEach(() => {
      initialArray = [1]; // Arrange
      initialArray.push(2); // Act
    });

    it('appends x to the end of the Array', () => {
      expect(initialArray).toEqual([1, 2]); // Assert
    });
  });
});

The AAA pattern is well known and recommended. Posting comments to spell out each section is not recommended and should be avoided.

Follow Test-Driven Development

Test-Driven Development is a robust way of designing software components ("units") interactively so that their behavior is specified through unit tests. Consider writing the tests before the code in a red-green-refactor style. Consequences of the test-first cycle:

  • Writing a test first makes the code design testable indeed;
  • Writing just the amount of code needed to implement the required functionality makes the resulting codebase minimal, thus more maintainable;
  • The codebase can be enhanced using refactoring mechanisms: The tests give us confidence that the new code is not modifying the existing functionalities;
  • Cleaning the code in each cycle makes the codebase more maintainable: It is much cheaper to change the code frequently and in small increments;
  • Fast feedback for the developers: We know that we don't break anything and that we are evolving the system in a good direction;
  • Generates confidence to add features, fix bugs, or explore new designs.

Follow the FIRST Principles

Acronym FIRST stand for below test features:

  • [F]ast: Unit tests should be fast otherwise they will slow down the development/deployment time and will take longer time to pass or fail;
  • [I]solated: Never ever write tests which depend on other test cases;
  • [R]epeatable: A repeatable test is one that produces the same results each time we run it.
  • [S]elf-validating: Each test must be able to determine that the output is expected or not. There must be no manual interpretation of results.
  • [T]imely: We can write unit tests at any time.

Describe expectations in a human language

Label the test suites (describe blocks) and specs (it blocks) in a way that clearly conveys the intention of each unit test. Note that the name of each test is the title of its it preceded by all its parent describe names. Favor assertive verbs and avoid ones like "should". Thus, test suite becomes documentation for our codebase (helpful for new team members and non-technical stakeholders), failure messages accurately depict what is broken and forces good naming conventions in tested code.

Name the tests properly

Tests names should be concise, explicit, descriptive and in correct English. Read the output of the spec runner and verify that it is understandable. Keep in mind that someone else will read it too. Tests can be the live documentation of the code. For more details, see the next example:

describe('The Gallery instance', () => {
  describe('when initialized', () => {
    it('properly calculates the thumb size', () => {});

    it('properly calculates the thumbs count', () => {});
  });
});

Structure the tests properly

Don't hesitate to nest our suites to structure logically our tests in subsets. For more details:

describe('A set of functionalities', () => {
  it('does something nice', () => {});

  describe('A subset of functionalities', () => {
    it('does something great', () => {});

    it('does something awesome', () => {});
  });

  describe('Another subset of functionalities', () => {
    it('also do something great', () => {});
  });
});

This organization allows tests to build on each other from least to most specific, creates tests that are easy to extend and/or refactor, makes branch testing easier and less repetitive and encapsulates tests based on their common denominator.

Create new tests for every defect

Regression tests should be written for bug fixes to prevent them from recurring in the future. Start by creating a test that replicates the problem before touching any code. From there, we can apply Test-Driven Development as usual to fix it. Identifying bugs is one of the crucial phases in the software development lifecycle. Tracking the bug ensures quality assurance of software as well as eliminates the risk of post-release glitches. This will prevent the same bug from happening again.

Mock new Date() and Date.now

There are situations where new Date() or Date.now is used in application code. Date.now() returns the unix time, ie. "the number of milliseconds elapsed since January 1, 1970 00:00:00 UTC.". new Date() returns a new Date object, and behaves differently based on the input passed to it. If called with nothing, it returns the current Date. We must mock dates to obtain deterministic tests. In this case, we should know how the test framework works. For Jasmine, there is information in the Mocking the Date section of the official documentation. Dates are faked by default in Jest environments.

Mock out all external services and state

When we run tests, the last thing we want to do is modify the external resources. We therefore need to make sure that our unit tests are "stateless," so that we can run them whenever we need to, without cleaning our development environment for test conditions. Otherwise, behavior in those external services overlaps multiple tests, and state data means that different unit tests can influence each other's outcome. An additional benefit of using a mock environment is that tests run there much faster than they would via the external resources that are already currently functioning in real time.

Do not test external libraries

Libraries are an integral part of any JavaScript developer's life. The general advice would be to not test library internals but expect that the library knows what it's supposed to do and has test coverage on its own. For example, we have a function that does nothing else but invoking the library function. There is no value in this, besides, it is adding code to the test suite. Better is to test it in the way the user interacts with it.

Do not mock everything

In unit tests it is supposed to mock all external dependencies. However, we don't need to mock everything. The idea to keep in mind is that dependencies can still be "real" objects. Consider using the "real" version of the objects if:

  • It leads to a simple, nice and easy tests setup;
  • It does not create a shared state between the tests, causing unexpected side effects;
  • The code being tested does not make AJAX requests, API calls or browser page reloads;
  • The speed of execution of the tests stays within the limits fixed.

Do not test multiple concerns

If a method has several end results, each one should be tested separately. Whenever a bug occurs, it will help us locate the source of the problem. See the next example:

it('sends the profile to the server and updates the profile view', () => {
  // expect(...)to(...);
  // expect(...)to(...);
});

Be careful when writing "AND" or "OR" when naming tests because is a code smell. For the previous example, it is better to change to:

it('sends the profile to the server', () => {
  // expect(...)to(...);
});

it('updates the profile view', () => {
  // expect(...)to(...);
});

Do not skip unit tests

Tests have a reason to be or not. Don't comment them out because they are too slow, too complex or produce false negatives. Instead, make them fast, simple and trustworthy. If not, remove them completely. Do not use xdescribe or xit to skip their execution. Use no-disabled-tests and no-focused-tests lint rules of eslint-plugin-jasmine. These rules will disallow use of disabled and focused tests.

Do not unit-test configuration settings

The configuration settings aren't part of any unit of code. That's why we extracted the setting out in some properties file. Even if we could write a unit test that inspects the configuration, we should write only single or two test cases for verifying that configuration loading code is working. Testing all the configuration settings in each separate test cases proves only one thing: "We know how to copy and paste". To avoid this scenario, we can use snapshot tests to check the entire contents of the file.

Do not overuse variables

A usual reflex of a developer is to extract values that are used multiple times to variables. Unfortunately, this significantly bloats the test code. Moreover, given a test failure message, it's harder to trace the value back to the relevant line of code. If we keep the tests short, it's no problem to see where the same values are used. For more details, see the next example:

it('contains the item', () => {
  const expected = Repository.getById(4243);

  expect(expected.id).toBe(4243);
});

Do not use static access

Static access is an anti-pattern. First, it obfuscates dependencies and side-effects making the whole code harder to understand and more error-prone. Second, static access harms testability. We can't exchange the objects anymore. But in a test, we want to use mocks or use the real objects with a different configuration. So instead of access code statically, put it into non-static methods, instantiate the class and pass the object to the constructor of the object. Do as in the next example:

class ProductController {
  constructor(dao) {
    this._dao = dao;
  }

  getProducts() {
    return this._dao.getProducts();
  }
}

Do not reuse production code

Test should test the production code and not reuse it. If we reuse production code in a test, we might miss a bug that is introduced in the reused code because we don't test this code anymore. Instead, we think in terms of input and output when writing tests. The test sets the input and compares the actual output with hard-coded values. Most of the time, code reuse is not required.

Do not rewrite production logic

Mapping code is a common example where the logic in tests is rewritten. So let's assume our tests contains a function mapEntityToDto() which result is used to assert that a returned DTO contains the same values than the entities that have been inserted at the beginning of the test. In this case, we'll most likely end up rewriting the production logic in the test code, which can contain bugs.

it('#requestProductById returns a ProductDTO', () => {
  const actualDTO = requestProductById(1);
  // The same mapping logic as the production code
  const expectedDTO = mapEntityToDto(new Product(1, 'name'));

  expect(actualDTO).toEqual(expectedDTO);
});

The solution is to compare the actualDTO with a manually created reference object with hard-coded values. That's dead-simple, easy to understand and less error-prone.

Do not catch errors. Expect them

When trying to assert that some input triggers an error, it might look right to use try-catch-finally and asserts that the catch clause was entered. The result is an awkward and verbose test case that hides the simple test intent and the result expectations. A more elegant alternative is the using the one-line dedicated assertion:

it('adds a user in memory', () => {
  expect(userManager.addUser()).toThrow(new Error());
});

It's recommended to also ensure the exception contains a property that tells the error type, otherwise given just a generic error the application won't be able to do much rather than show a disappointing message to the user.

Do not test complex user interactions

The complexity of writing tests is a good measure of the complexity of the code. However, in some cases, some scenarios are out of the scope of unit tests. Examples of complex user interactions:

  • Filling a form, drag and dropping some items then submitting the form;
  • Clicking a tab, clicking an image thumbnail then navigating through a gallery of images previously loaded from a database.

These interactions might involve many units of work and should be handled at a higher level by functional tests. Instead, test simple user actions. Examples of simple user actions:

  • Clicking on a link that toggles the visibility of a DOM element;
  • Submitting a form that triggers the form validation.

These actions can be easily tested by simulating DOM events, for example, when a "click" event occurs, a public method is called.

Do not Repeat Yourself

Use before/after blocks to DRY up repeated setup, teardown, and action code. This organization keeps test suite more concise and readable. Changes only need to be made in one place. For more details, see the next example:

describe('Array .push(x)', () => {
  let initialArray, pushResult;

  beforeEach(() => {
    initialArray = [1];
    pushResult = initialArray.push(2);
  });

  it('appends x to the end of the Array', () => {
    expect(initialArray).toEqual([1, 2]);
  });

  it('returns x', () => {
    expect(pushResult).toBe(2);
  });
});

Avoid toBeTruthy or toBeFalsy

Jasmine and Jest also provide following matchers: toBeTruthy and toBeFalsy. We should not use them because they make tests weaker and produce false-positive results. For example, expect(someBoolean).toBeFalsy() passes when someBoolean === null, and when someBoolean === false. Both have the tricky toBeDefined matcher that can produce false positive test. Because it validates the given value for undefined only.

Avoid the All's

Prefer beforeEach/afterEach blocks over beforeAll/afterAll ones. The latter are not reset between tests. Replacing All blocks by Each blocks we will avoid accidental state leak, enforce test independence and improve test readability because the order of All block execution relative to Each ones is not always obvious.

Avoid mocks in favor of stubs and spies

We got to stub some dependencies since we can't do everything in our tests as we do in a real environment. Our tests shouldn't depend on anything outside and they should be isolated. Therefore, we stub all the dependencies that commit side effects so that we can just test what we want to test in isolation. We just stub any network request code. We watch what we want to check is called with spies. We avoid mock any server-side interactions with the spies approach.

Avoid global test fixtures and seeds

We should create our data per test and clean them out after each test. This way, we always get a clean environment for our tests. Therefore, the tests won't depend on each other. This is important since we'll run into problems when tests depend on each other. If performance becomes a concern with creating data for each test, then we've to simplify the data. So, if we test with database interaction, we got to remove all the data after each test.

Avoid logic in the tests

The logic of code inherently requires a premise, a condition, and a conclusion. If a test were to include logic, therefore, it would not be a "one-concern" test. Furthermore, we simply don't want to write bugs into our tests, and we're at risk of that when we incorporate logic. We always use simple statements. Don't use loops, switch cases and/or conditionals. If we do, we add a possible entry point for bugs in the test itself:

  • Conditionals: we don't know which path the test will take;
  • Loops: we could be sharing state between tests.

It´s better to write a test for each scenario. When we test only one concern per test, we can evaluate our code precisely. It will give a nice output of all possible cases, improving maintainability.

Prefer toBe over toEqual for primitive values

Jasmine and Jest have toBe and toEqual matchers. As toBe uses Object.is to compare values, it's faster (by default) than using toEqual. While the latter eventually falls back to leverage Object.is, for primitive values, it should only be used when complex objects need a comparison. toEqual recursively checks every field of an object or array.

Cover the general case and the edge cases

"Strange behavior" usually happens at the edges. Remember that the tests can be the live documentation of our code. In software testing, code coverage and test coverage are important metrics. They are important benchmarks by which to measure the effectiveness of the codebase. Code coverage is performed to verify the extent to which the code has been executed. The test coverage report provides information about parts of the software where test coverage is being implemented.

Test only public methods

Testing the internals brings huge overhead for almost nothing. If the code/API delivers the right results, should we really invest our time in testing how it worked internally and then maintain these fragile tests? Whenever a public behaviour is checked, the private implementation is also implicitly tested, and the tests will break only if there is a certain problem (e.g. wrong output). This approach is also referred to as behavioural testing.

Test the behaviour and not the implementation

It is recommended to check the result of an operation and not the internal implementation. With this approach, changing the internal implementation of a class/object will not necessarily force us to refactor the tests. In the next example, we have a bad example because we are testing the internal implementation.

it('adds a user in memory', () => {
  userManager.addUser('Dr. Falker', 'Joshua');

  expect(userManager._users[0].name).toBe('Dr. Falker');
  expect(userManager._users[0].password).toBe('Joshua');
});

Test asynchronous code with async/await

When testing Promises we should always make sure that the test is asynchronous, and rejections are handled. It's recommended to use the async/await syntax in the test suite:

it('tests a promise', async () => {
  const users = await fetchUsers();

  expect(users.length).toBe(42);
});

Using the done and done.fail callbacks is discouraged when working with promises. They should only be used when testing callback-based code.

Test many input combinations

Typically, we choose a few input samples for each test. However, in production, an API that is called with 5 parameters can be invoked with thousands of different permutations. We should test many input combinations. This way, we won't only choose cases that we know will make our test pass. We can make the values random. For example, with the fast-check or jsverify library, we can create random combinations of data for our tests.

Use lint rules

Linters can catch severe issues like errors that are not thrown correctly and losing information. Having lint rules in place means that we will get a nice error when we are doing something that we should not be. This will enforce consistency in our application and readability. On top of the basic set of rules (like ESLint standard or Airbnb style), consider including some specializing Linters. eslint-plugin-promise can discover promises with no resolve. eslint-plugin-security which can discover eager regex expressions that might get used for DOS attacks. eslint-plugin-jest or eslint-plugin-jasmine they will show a warn when tests have no assertions at all or when tests are skipped which might lead to a false belief that all tests are passing.

Use realistic input data

Many times, it so happens that the testers use the inputs that are not realistic or practical to the real-life scenarios. Often production bugs are revealed under some very specific and surprising input. So, we should always use realistic inputs while testing our application. The more realistic the test input is, the greater the chances are to catch bugs early. Use dedicated libraries like Faker to generate pseudo-real data that resembles the variety and form of production data.

Use factory functions

A factory function is any function which is not a class or constructor that returns a (presumably new) object. In JavaScript, any function can return an object. When it does so without the new keyword, it's a factory function. Factories can:

  • Help reduce the setup code, especially if we use dependency injection ot to encapsulate complex code;
  • Make each test more readable, since the creation is a single function call that can be in the test itself instead of the setup;
  • Provide flexibility when creating new instances (setting an initial state, for example).

Use the prefixes "actual" and "expected"

If we are going to use variables in an equals assertion, prefix the variables with actual and expected. This increases the readability and clarifies the intention of the variable. Moreover, it's harder to mix them up in the equals assertion.

it('appends x to the end of the Array', () => {
  const actualArray = [1, 2];
  const expectedArray = INITIAL_ARRAY.concat([2]);

  expect(actualArray).toEqual(expectedArray);
});

Tests should be isolated and atomic

Every test should run independently and without being dependant on each other. If neither test is dependent on any other test, then if one test fails, other tests are not affected. Also, the tests should follow the atomicity property. It should not fail in between suddenly. A test should be entered and exited with the pass or fail result smoothly. We should also keep in mind that the data we are testing upon should be separate for every test.

Design for lean testing

Testing code is not like production-code. Design it to be dead-simple, short, abstraction-free, flat, delightful to work with, lean. One should look at a test and get the intent instantly. Test only as much as needed, strive to keep it nimble, sometimes it's even worth dropping some tests and trade reliability for agility and simplicity.

Categorize tests under at least 2 levels

Apply some structure to the test suite so an occasional visitor could easily understand the requirements and the various scenarios that are being tested. A common method for this is by placing at least 2 "describe" blocks above the tests. The first is for the name of the unit under test and the second for additional level of categorization like the scenario or custom categories. Doing so will also greatly improve the test reports. In addition, it will get much easier for a developer to navigate through the code of a suite with many tests.

Shorten the feedback loop

An efficient testing process constitutes many and iterative loops: (1) try-outs -> (2) feedback -> (3) refactor. The faster the feedback is the more improvement iterations a developer can perform per-module and perfect the results. We can get feedback faster is we run CI locally on the developer's machine. So, we can write our code, get feedback, and then make changes as needed.

Tag the tests

Different tests must run on different scenarios: quick smoke, IO-less, tests should run when a developer saves or commits a file, full end-to-end tests usually run when a new pull request is submitted, etc. This can be achieved by tagging tests with keywords like #services, #api, #sanity so we can grep with the testing harness and invoke the desired subset. Otherwise, running all the tests any time, a developer makes a small change can be extremely slow and keeps developers away from running tests.

Focus on test coverage

Coverage is a measure of how many code lines (and branches, statements, etc.) are being reached by the tests. So how much is enough? 10–30% is obviously too low to get any sense about the build correctness, on the other side 100% is very expensive and might shift the focus from the critical paths to the exotic corners of the code. The long answer is that it depends on many factors like the type of application. Although most of the testing enthusiasts claim that the right coverage threshold is contextual, most of them also mention the number 80% as a thumb of a rule that presumably should satisfy most of the applications.

Analyse the test coverage report

Some issues sneak just under the radar and are hard to find using traditional tools. These are not really bugs but more of surprising application behaviour that might have a severe impact. For example, often some code areas are never or rarely being invoked. If we don't know which parts of our code are left un-tested, we don't know where the issues might come from.

Avoid duplicate coverage

Don´t create tests for features coverage by other tests. Let's say we've created a new UI component. If we can cover the functionality in a unit test, we should do it. Unit tests are generally easier to maintain, less flakey, and less expensive to run in our CI pipeline. UI tests should be covering the areas only they can cover. Usually, these are the big-picture user stories that span many components and views.

Measure logical coverage

The traditional coverage metric often lies. It may show us 100% code coverage, but none of our functions, even not one, return the right response. It simply measures over which lines of code the test visited, but it doesn't check if the tests actually tested anything. We can use mutation testing to tell which part of our app is tested rather than just visited. To do that, we can intentionally change the values to check the outcomes as a result of them. We may uncover cases that should fail that doesn't come up that we may have not covered yet.

Follow the Testing Pyramid

We should try to follow the test automation pyramid. Based on Test Pyramid, the unit test should be taken as the base of all the testing. We do so because the unit test will cover basic units of functionality independently of one another. After the unit tests are done, then move ahead to the integration testing. Integration testing will let us test the different modules combined with one another as a group. After that, we move on to the next part of the pyramid and test the front-end or User-Interface testing using Selenium or similar tools. The cost incurred continues to increase as we move to the top of the pyramid, but the speed continues to decrease.

Parallelize test execution

Parallel testing means running multiple test cases, simultaneously. Running different tests in parallel has its own advantages. If we are not following parallelism, then we will run one test and provide the feedback about it then, we will run other tests and provide feedback about it and so on. These feedbacks are then analysed and are worked upon. Then, the team will check the feedback of the second test we did and then resolve them. While following parallelism, we can drastically reduce the feedback loop and provide feedback of many tests altogether which can be resolved in a lesser time as before. This way, we can save a lot of time and resources of the company.

Know the testing framework API

The API documentation of the testing framework/library should be our bedside book. Having a good knowledge of the API can help us in reducing the size/complexity of the test code and, in general, help us during development. A simple example:

it('calls a method with the proper arguments', () => {
  const foo = { bar: jasmine.createSpy() };

  foo.bar('qux');

  expect(foo.bar).toHaveBeenCalled();
  expect(foo.bar.calls.argsFor(0)).toEqual(['qux']);
});

It is simpler and more readable if done as follows:

it('calls once a method with the proper arguments', () => {
  const foo = jasmine.createSpyObj('foo', ['bar']);

  foo.bar('baz');

  expect(foo.bar).toHaveBeenCalledWith('baz');
});

Bibliography

Author: Andredesousa
Source Code: https://github.com/andredesousa/javascript-unit-testing-best-practices 
License: MIT license

#javascript #testing #unit 

A guideline of best practices that you can apply to your JavaScript

Heartbeat: A CakePHP Plugin Providing an App Heartbeat Status Page

Heartbeat

A CakePHP plugin providing an application heartbeat status page with configurable sensors.

Compatibility

Plugin VersionCakePHP CompatibilityBranchStatus
2.x3.7+cakephp-3.xSupported
1.x2.xcakephp-2.xSupported
0.x2.x-EOL

Note:

  • There is no plugin version for CakePHP 3.0-3.5.
  • Previous versions of the plugin that supported previous versions of CakePHP are not supported anymore

Installation

Requirements

  • PHP >= 7.0
  • CakePHP 3.7+

CakePHP Version Support

This version of the plugin supports CakePHP 3.x only.

Installation via composer

First, require the package through Composer:

composer require orca-services/cakephp-heartbeat

Then load the plugin in your application as documented in the section Loading a Plugin in the CakePHP CookBook.

Installation alternatives

Refer to the CakePHP CookBook section Manually Installing a Plugin.


Configuration

General

The configuration can be set in App.Heartbeat.
It takes the following subkeys:

  • name The name of your application (will be used for the title of the hearbeat status page)
  • layout To override the layout (see below)
  • Sensors An array of sensors (see below)

An example configuration would look like this:

$config['App']['Heartbeat'] = [
    'name' => 'My App',
    'layout' => 'heartbeat',
    'Sensors' => [
        'Debug-Mode' => [
            'enabled' => true,
            'severity' => 1,
            'class' => OrcaServices\Heartbeat\Heartbeat\Sensor\DebugMode::class,
        ],
        'DB Connection' => [
            'enabled' => true,
            'severity' => 3,
            'class' => OrcaServices\Heartbeat\Heartbeat\Sensor\DBConnection::class,
            'cached' => true,
        ],
        'DB up to date' => [
            'enabled' => false,
            'severity' => 3,
            'class' => OrcaServices\Heartbeat\Heartbeat\Sensor\DBUpToDate::class,
            'cached' => '+10 minutes',
        ],
    ],
];

Sensors

You can add your own sensor to your heartbeat status. See How to write a Sensor for details.
To add your sensor to your status page, you have to add it to your configuration array. The sensor array takes the names of your registered sensors as subkeys, which in turn contain configuration arrays.

Those take the following subkeys:

  • enabled can be true or false; to enable or disable a sensor
  • severity can be:
    • 1: Informational
    • 2: Non critical
    • 3: Critical
  • class The fully qualified class name (FQCN)
  • chached true, false or a string
    • If set to false, the value will not be cached.
    • If set to true, the value will be cached for 30 seconds (by default).
    • Can be set to a relative time string e.g. +10 minutes to cache the value for 10 minutes.

Layout overriding

You can override the default layout with your own to match the styling of your application. For the example above, you should create a file named heartbeat.ctp in your View/Layouts folder. In there, you can define a custom layout and load custom assets, such as JavaScript & CSS.


How to use

Controller

The heartbeat status page can be accessed via /heartbeat, e.g. http://www.example.com/heartbeat or http://localhost/my_app/heartbeat. It will display a table of all the registered and enabled sensors and their status, as well as the overall status of your application, based on the sum of all non-informational sensor statuses:

Heartbeat

Or, if you use a basic bootstrap layout instead (see the Configuration on how to change the layout):

Heartbeat_Bootstrap

The data can also be requested as JSON, e.g. for monitoring. Just append .json to the URL e.g. http://www.example.com/heartbeat.json:

Heartbeat_JSON

To reset the cached sensor status results and to force to load the status page without caching, you can add ?reset-cache=true to the URL, e.g. http://www.example.com/heartbeat?reset-cache=true.

Console Application

TODO Not yet implemented.


Built-in Sensors

DB Connection

Checks whether a connection to the database server can be established.

DB Up to date

Uses the Migrations Plugin to check whether all migrations have been run.

If you use a version of cakephp/migrations below 2.2, you will need to load the cakephp/migrations plugin before the sensor is called.

Debug Mode

Outputs the configuration for the debug mode.

How to Write a Heartbeat Sensor

If you would like to add a new sensor to the heartbeat, e.g. to monitor an API, you can do that easily. In this example, we will add a sensor for 'My API'.

First, create a class for the sensor wherever you like, e.g. src/Heartbeat/Sensor. The class for this example will be named MyApi. This class has to extend OrcaServices\Heartbeat\Heartbeat\Sensor and implement the abstract method _getStatus().

In most cases, this method should return true or false to imply whether the action to check was successful or not. It can also return other, purely informational data, e.g. the version number, but that only makes sense for an informational status (as defined in the configuration).

We assume that, to check the API status, we have an ApiClient class somewhere in the project and that class has a method called ping() which returns 'Pong' as answer from the API.

In this example, the Sensor would look like this:

<?php
namespace Heartbeat\Sensor;

use Exception;
use OrcaServices\Heartbeat\Heartbeat\Sensor;
use Api\ApiClient;

class MyApi extends Sensor
{
    protected function _getStatus()
    {
        try {
            $client = new ApiClient();
            $ping = $client->ping();

            return $ping['message'] == 'Pong';
        } catch (Exception $exception) {
            return false;
        }
    }
}

Now we just have to load our new sensor in the configuration, e.g:

$config['App']['Heartbeat'] = [
    'name' => 'My App',
    'layout' => 'heartbeat',
    'Sensors' => [
        'Debug-Mode' => [
            'enabled' => true,
            'severity' => 1,
            'class' => OrcaServices\Heartbeat\Heartbeat\Sensor\DebugMode::class,
        ],
        'DB Connection' => [
            'enabled' => true,
            'severity' => 3,
            'class' => OrcaServices\Heartbeat\Heartbeat\Sensor\DBConnection::class,
            'cached' => true,
        ],
        'DB up to date' => [
            'enabled' => false,
            'severity' => 3,
            'class' => OrcaServices\Heartbeat\Heartbeat\Sensor\DBUpToDate::class,
            'cached' => '+10 minutes',
        ],
        'REST API' => [
            'enabled' => true,
            'severity' => 2,
            'class' => Heartbeat\Sensor\MyApi::class,
            'cached' => '+15 minutes',
        ],
    ],
];

Back to the Documentation.

Versioning

The releases of this plugin are versioned using SemVer.

Security

Security Policy

Supported Versions

We generally support fixing security issues in all sensible releases. We may decide not to fix them in very old releases, though.

Reporting a Vulnerability

If you’ve found a security issue in one of our packages, please send us an email to development [at] orca.ch instead of using the normal bug reporting system or any other form of notification.

Once we receive a vulnerability report, we first confirm to the reporter that we simply received the report.

Next, for each report, we try to confirm the vulnerability. Once confirmed, we will do the following:

  • Acknowledge to the reporter that we’ve confirmed the issue, and are working on a fix. We ask the reporter to keep the issue confidential until we announce a solution.
  • Get a fix/patch or workaround/guidance prepared.
  • Release new versions of all affected versions, if applicable.
  • Prominently feature the problem in the release description, if applicable.

Contributing

See CONTRIBUTING.md

Changelog

See CHANGELOG.md

TODOs

  • Add badges
  • Fix & extend Unit Tests
  • Add Console application incl. related docs
  • Support for separate status text
  • Add flexible routing
  • CI integrations
  • Update screenshots in How to Use with new cache indicator
  • See the issues

Author: orca-services
Source Code: https://github.com/orca-services/cakephp-heartbeat/ 
License: MIT license

#php #cakephp #services #hacktoberfest 

Heartbeat: A CakePHP Plugin Providing an App Heartbeat Status Page
Nigel  Uys

Nigel Uys

1654767780

Flexible HTTP Command Line Stress Tester for Websites & Web Services

Pewpew   

Pewpew is a flexible command line HTTP stress tester. Unlike other stress testers, it can hit multiple targets with multiple configurations, simulating real world load and bypassing caches.

Disclaimer: Pewpew is designed as a tool to help those developing web services and websites. Please use responsibly.

Demo

Features

  • Multiple modes for measuring servers
  • Regular expression defined targets
  • Multiple simultaneous targets
  • No runtime dependencies, single binary file
  • Statistics on timing, data transferred, status codes, and more
  • Export raw data as TSV and/or JSON for analysis, graphs, etc.
  • HTTP2 support
  • IPV6 support
  • Tons of command line and/or config file options (arbitrary headers, cookies, User-Agent, timeouts, ignore SSL certs, HTTP authentication, Keep-Alive, DNS prefetch, and more)

Installing

Pre-compiled binaries for Windows, Mac, Linux, and BSD are available on Releases.

If you want to get the latest or build from source: install Go 1.11+ and either go get github.com/bengadbois/pewpew or git clone this repo.

Modes

Pewpew features two independent modes: stress and benchmark.

Stress mode (pewpew stress) sends requests as fast as the server can respond (limited by concurrency). This mode is usually best for answering questions such as "how fast can the server return 1000 requests?", "will the server ever OOM?", "can I get the server to 503?", and more related to overloading.

Benchmark mode (pewpew benchmark) sends requests at a fixed rate (requests per second). This mode is usually best for anwering questions such as "how much traffic can the server handle before latency surprasses 1 second?", "if traffic to the server is rate limited to 100 rps, will there by any 503s?", and other measurable controlled traffic tests.

Examples

pewpew stress -n 50 www.example.com

Make 50 requests to http://www.example.com

pewpew benchmark --rps 100 --duration 60 www.example.com

For 60 seconds, send 100 requests each second to www.example.com

pewpew stress -X POST --body '{"hello": "world"}' -n 100 -c 5 -t 2.5s -H "Accept-Encoding:gzip, Content-Type:application/json" https://www.example.com:443/path localhost 127.0.0.1/api

Make request to each of the three targets https://www.example.com:443/path, http://localhost, http://127.0.0.1/api

  • 100 requests total requests per target (300 total)
  • 5 concurrent requests per target (15 simultaneous)
  • POST with body {"hello": "world"}
  • Two headers: Accept-Encoding:gzip and Content-Type:application/json
  • Each request times out after 2.5 seconds

For the full list of command line options, run pewpew help or pewpew help stress

Using Regular Expression Targets

Pewpew supports using regular expressions (Perl syntax) to nondeterministically generate targets.

pewpew stress -r "localhost/pages/[0-9]{1,3}"

This example will generate target URLs such as:

http://localhost/pages/309
http://localhost/pages/390
http://localhost/pages/008
http://localhost/pages/8
http://localhost/pages/39
http://localhost/pages/104
http://localhost/pages/642
http://localhost/pages/479
http://localhost/pages/82
http://localhost/pages/3
pewpew stress -r "localhost/pages/[0-9]+\?cache=(true|false)(\&referrer=[0-9]{3})?"

This example will generate target URLs such as:

http://localhost/pages/278613?cache=false
http://localhost/pages/736?cache=false
http://localhost/pages/255?cache=false
http://localhost/pages/25042766?cache=false
http://localhost/pages/61?cache=true
http://localhost/pages/4561?cache=true&referrer=966
http://localhost/pages/7?cache=false&referrer=048
http://localhost/pages/01?cache=true
http://localhost/pages/767911706?cache=false&referrer=642
http://localhost/pages/68780?cache=true

Note: dots in IP addresses must be escaped, such as pewpew stress -r "http://127\.0\.0\.1:8080/api/user/[0-9]{1,3}"

Using Config Files

Pewpew supports complex configurations more easily managed with a config file. You can define one or more targets each with their own settings.

By default, Pewpew looks for a config file in the current directory and named pewpew.json or pewpew.toml. If found, Pewpew can be run like:

pewpew stress

There are examples config files in examples/.

Pewpew allows combining config file and command line settings, to maximize flexibility. Pewpew uses https://github.com/spf13/viper and follows its rules of config precedence.

Other Options

The full list of options for each command can be viewed by running Pewpew with the --help flag.

Using as a Go library

package main

import (
    "fmt"
    "os"

    pewpew "github.com/bengadbois/pewpew/lib"
)

func main() {
    stressCfg := pewpew.StressConfig{
        Count:       1,
        Concurrency: 1,
        Verbose:     false,
        Targets: []pewpew.Target{{
            URL: "https://127.0.0.1:443/home",
            Options: pewpew.TargetOptions{
                Timeout: "2s",
                Method:  "GET",
                Body:    `{"field": "data", "work": true}`,
            },
        }},
    }

    output := os.Stdout
    stats, err := pewpew.RunStress(stressCfg, output)
    if err != nil {
        fmt.Printf("pewpew stress failed:  %s", err.Error())
    }

    fmt.Printf("%+v", stats)
}

Full package documentation at godoc.org

Hints

If you receive a lot of "socket: too many open files" errors while running many concurrent requests, try increasing your ulimit.

Author: Bengadbois
Source Code: https://github.com/bengadbois/pewpew 
License: MIT license

#go #golang #http #testing #services 

Flexible HTTP Command Line Stress Tester for Websites & Web Services

Netbug: Easy Remote Profiling Of Your Services

netbug

Package netbug provides access to an http.Handler that accesses the profiling and debug tools available in the /net/http/pprof and /runtime/pprof packages.

The advantages of using netbug over the existing /net/http/pprof handlers are:

  1. You can register the handler under an arbitrary route-prefix. A use-case might be to have a secret endpoint for keeping this information hidden from prying eyes, rather than /debug/pprof;
  2. It pulls together all the handlers from /net/http/pprof and /runtime/pprof into a single index page, for when you can't quite remember the URL for the profile you want;
  3. You can register the handlers onto http.ServeMux's that aren't http.DefaultServeMux;
  4. It provides an optional handler that requires a token URL parameter. This is useful if you want that little bit of extra security (use this over HTTPS connections only).

Note: It still imports /net/http/pprof, which means the /debug/pprof routes in that package still get registered on http.DefaultServeMux. If you're using this package to avoid those routes being registered, you should use it with your own http.ServeMux.

netbug is trying to cater for the situation where you want all profiling tools available remotely on your running services, but you don't want to expose the /debug/pprof routes that net/http/pprof forces you to expose.

How do I use it?

In the simplest case give netbug the http.ServeMux you want to register the handlers on, as well as where you want to register the handler and you're away.

package main

import (
    "log"
    "net/http"

    "github.com/e-dard/netbug"
)

func main() {
    r := http.NewServeMux()
    netbug.RegisterHandler("/myroute/", r)
    if err := http.ListenAndServe(":8080", r); err != nil {
        log.Fatal(err)
    }
}

Visiting http://localhost:8080/myroute/ will then return:

netbug also provides a simple way of adding some authentication:

package main

import (
    "log"
    "net/http"

    "github.com/e-dard/netbug"
)

func main() {
    r := http.NewServeMux()
    netbug.RegisterAuthHandler("password", "/myroute/", r)
    if err := http.ListenAndServe(":8080", r); err != nil {
        log.Fatal(err)
    }
}

And visit http://localhost:8080/myroute/?token=password.

Obviously this form of authentication is pointless if you're not accessing the routes over an HTTPS connection. If you want to use a different form of authentication, e.g., HTTP Basic Authentication, then you can use the handler returned by netbug.Handler(), and wrap it with handlers provided by packages like github.com/abbot/go-http-auth.

What can you do with it?

It just wraps the behaviour of the /net/http/pprof and /runtime/pprof packages. Check out their documentation to see what's available. As an example though, if you want to run a 30-second CPU profile on your running service it's really simple:

$ go tool pprof https://example.com/myroute/profile

New in Go 1.5

You can now produce execution traces of your remotely running program using netbug.

To do this run one of the trace profiles, which will result in a file being downloaded. Then use the Go trace tool to generate a trace, which will open up in your browser.

$ go tool trace binary-being-profiled /path/to/downloaded/trace

When compiling binary-being-profiled, you will need to have targeted the same architecture as the binary that generated the profile.

Background

The net/http/pprof package is great. It let's you access profiling and debug information about your running services, via HTTP, and even plugs straight into go tool pprof. You can find out more about using the net/http/pprof package at the bottom of this blog post.

However, there are a couple of problems with the net/http/pprof package.

  1. It assumes you're cool about the relevant handlers being registered under the /debug/pprof route.
  2. It assumes you're cool about handlers being registered on http.DefaultServeMux.
  3. You can't wrap the handlers in any way, say to add authentication or other logic.

You can sort of fix (1) and (2) by digging around the net/http/pprof package and registering all all the exported handlers under different paths on your own http.ServeMux, but you still have the problem of the index page—which is useful to visit if you don't profile much—using hard-coded paths. It doesn't really work well. Also, the index page doesn't provide you with easy links to the debug information that the net/http/pprof package has handlers for.

netbug is just a small package to fix these issues.

Author: e-dard
Source Code: https://github.com/e-dard/netbug 
License: MIT license

#go #golang #services 

Netbug: Easy Remote Profiling Of Your Services

Building Trust by Using Technology: A Path towards Digital Transformat

When customers like your products and services, does it mean they totally trust you?. Well, technically the answer is no. Because it is not just about products and services. But it is also about the core purpose and the ethics of your organization serving as the fundamental parameters to gain a better level of trust from your customers. To build enough trust is a matter of choosing the right practices empowered with technology to communicate the brand personality to your audience.

https://brainstreamtechnolabs.com/building-trust-by-using-technology-a-path-towards-digital-transformation/

#digitaltransformation #digitalization #organization #services #technology #newblog #newarticle #product #digitaltrust  

Building Trust by Using Technology: A Path towards Digital Transformat
Joshua Yates

Joshua Yates

1652925418

How to Create Your Own Portfolio Website with HTML, CSS & JavaScript

The Ultimate Guide To Create A Complete Portfolio Website Using HTML CSS And JavaScript 🤯

Build Your Personal Portfolio ➡️ Showcase Your Skills ➡️ GET HIRED! 🔥

Your personal portfolio is one of the most important things in order to showcase your work and skills. An excellent portfolio website will immediately outshine you and put you ten steps ahead ✨

Learn how to build an amazing portfolio website using codedamn's playgrounds for absolutely FREE! 

Timestamp
0:00 Teaser
01:34 Starts Building Project for your Portfolio
04:50 Navigation Bar for website
12:46 Download Icons for Navigation Bar from Fontawesome
16:15 Build Homepage Design
24:04 Outro


How to Create a Portfolio Website Using HTML, CSS, JavaScript, and Bootstrap 5

In this blog post, I will discuss some of the benefits of creating a portfolio website. Then I'll show you how to create a beautiful responsive portfolio website for yourself using HTML, CSS, JavaScript and Bootstrap version 5.

Table Of Contents

  • Benefits of having a portfolio website
  • What is Bootstrap?
  • Folder Structure
  • How to Add a Navigation Menu to Your Portfolio
  • How to Add a Hero Header to the Portfolio
  • How to Make the About Section
  • How to Make the Services Section
  • How to Add Dark Background Color to Navbar on Page Scroll
  • How to Build the Portfolio Section
  • How to Build the Contact Section
  • How to Build the Footer Section
  • Adding Final Touches
  • Conclusion

Benefits of having a Portfolio Website

Having a portfolio website has several benefits, including:

  • it provides a platform to showcase your relevant skills and experience
  • it shows your personality
  • it lets hiring managers find you instead of you reaching out to them
  • you are easily searchable on search engines like Google

What is Bootstrap?

Bootstrap is a popular front-end CSS framework which is used to develop responsive and mobile friendly websites. The latest release of Bootstrap is version 5. You can find the official documentation of Bootstrap 5 here.

Folder Structure

We will now start working on creating the portfolio website.

First, let's create the folder structure. You can get the project starter files on GitHub. Also, you can visit here to see the live demo of this project.

Screenshot-from-2022-01-22-19-10-25

Project Folder Structure

The folder structure consists of index.html, style.css, and script.js files and an images folder. We'll write all CSS in the style.css file and the JavaScript in the script.js file .

In the index.html file, you can see the HTML boilerplate code with the Bootstrap CDN, font awesome kit, and a link to the external style sheet and JavaScript.

Here, the script.js file is loaded after loading all the HTML code.

How to Add a Navigation Menu to Your Portfolio

Now, let's work on adding a navigation menu in our project. It will help visitors find the relevant info they're looking for.

We will use Bootstrap's fixed-top class in nav element to keep the navbar at the top of the page. The navbar also has a navbar-brand class where we keep the name of the person as a brand.

<nav class="navbar navbar-expand-lg fixed-top navbarScroll">
        <div class="container">
            <a class="navbar-brand" href="#">Brad</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item active">
                        <a class="nav-link" href="#home">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#about">About</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#services">Services</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#portfolio">Portfolio</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#contact">Contact</a>
                    </li>
                </ul>
                
            </div>
        </div>
    </nav>

The navbar has the following features:

  • It has six links: home, about, services, portfolio, contact, and footer
  • It has a transparent background. We will add a dark background on page scrolling later.
  • It toggles on smaller devices

You can find more details regarding Bootstrap 5 navbar features here.

However, the navbar has a problem while scrolling. It's fully transparent throughout the page which causes readability issues.  We will fix this issue after we complete the Services section to make you understand the issue properly.

How to Add a Hero Header to the Portfolio

Now, we will be adding a hero image with some text in the center. A hero image is a web design term which refers to a high quality full width image that displays the company or individual's main goals, a representative image, photo, or other eye-catching elements. It helps attract users to your site.

 <!-- main banner -->
    <section class="bgimage" id="home">
        <div class="container-fluid">
            <div class="row">
            <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 hero-text">
                <h2 class="hero_title">Hi, it's me Brad</h2>
                <p class="hero_desc">I am a professional freelancer in New York City</p>
            </div>
            </div>
        </div>
    </section>

 Also, let's add the CSS for the above code in the style.css file:

/* hero background image */
.bgimage {
    height:100vh;
    background: url('images/heroImage.jpeg');
    background-size:cover;
    position:relative;
}
/* text css above hero image*/
.hero_title {
    font-size: 4.5rem;
}
.hero_desc {
    font-size: 2rem;
}
.hero-text {
    text-align: center;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: white;
}

Here we can see that the section has an id named bgimage which is responsible for displaying the background hero image with full width. It also displays some text in the center above the background image with the help of the above CSS.

This is how the site looks so far with the navbar and the hero section:

Screenshot-from-2022-01-25-10-13-25

Hero Image with Navbar

How to Make the About Section

The About page contains important information about you and your background. Visitors to your portfolio site can get to know you through the information you provide in this page.

We will be adding an image to the left side of the row, and on the right side we will add our quick introduction in this section. Let's demonstrate it using the code below:

<!-- about section-->
    <section id="about">
        <div class="container mt-4 pt-4">
            <h1 class="text-center">About Me</h1>
            <div class="row mt-4">
                <div class="col-lg-4">
                    <img src="images/about.jpeg" class= "imageAboutPage" alt="">
                </div>

                <div class="col-lg-8">
                    <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged
                        
                    </p>
                    <div class="row mt-3">
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                    </div>
                    <div class="row mt-3">
                        <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                            Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                        </p>
                    </div>
                </div>
            </div>
    </section>

Let's add some CSS for the left side image:

/* about section image css */
.imageAboutPage {
    width: 100%;
}

This will create an about section. You can modify the content based on your use cases. We have added classes named mt-4 and pt-4 with container class which will set the margin top and padding top to 1.5 rem.

The row has two columns. One has the col-lg-4 class for displaying the image which will occupy the left column with a 4-part grid for large screens.

The next column is assigned a class of col-lg-8 which will occupy the right column with an 8-part grid for larger screens. For medium and small screens they will overlap with each other which we can see in the below GIF file:

about

About Section

How to Make the Services Section

This section helps convert website visitors into potential clients. This is where you explain what specific services you offer, and where you niche down your offered services.

Let's add the code for this section and describe it below:

<!-- services section-->
    <section id="services">
        <div class="container">
            <h1 class="text-center">Services</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class="fas servicesIcon fa-clock"></i>
                            <h4 class="card-title mt-3">Website Development</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-layer-group'></i>
                            <h4 class="card-title mt-3">Website Design</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='far servicesIcon fa-check-circle'></i>
                            <h4 class="card-title mt-3">Website Deployment</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>

            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-search'></i>
                            <h4 class="card-title mt-3">SEO</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-shield-alt'></i>
                            <h4 class="card-title mt-3">DevOps</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-wrench'></i>
                            <h4 class="card-title mt-3">QA</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>
        </div>
    </section>

Since this website is targeted towards web developers and designers, I've included some of the services which a web developer or designer might offer.

We have used bootstrap cards to display services. Our services section has 2 rows and 3 columns each. For large screens with a width greater than or equal to 992px, three cards are displayed in a row. For screens less than 992px wide, only a single card is displayed in a row.

You can find more about bootstrap breakpoints here.

Also, there are fonts added in each card to make them look better.

Without CSS, the services section would look like this :

Screenshot-from-2022-01-23-14-01-00

So, let's add some CSS to increase the font icon font size and card height and add some extra color when a user hovers over a card.

/* services section css */
.servicesText.card {
    height: 280px;
    cursor: pointer;
  }
.servicesIcon {
    font-size: 36px;
    text-align: center;
    width: 100%;
}
.card-title {
    text-align: center;
}
.card:hover .servicesIcon {
    color: #008000;
}
.servicesText:hover {
    border: 1px solid #008000;
}

This is how our services section looks now:

services

Services 

How to Add Dark Background Color to Navbar on Page Scroll

If you look into the above gif properly you will see that the navbar is transparent throughout the page which causes readability issues. So let's work on fixing this issue.

We will write some JavaScript and CSS in order to resolve this problem. We will add a navbarDark class in order to show a dark background color for the navbar on page scroll.

For that we need to go to the script.js file and add the following code:

// add class navbarDark on navbar scroll
const header = document.querySelector('.navbar');

window.onscroll = function() {
    var top = window.scrollY;
    if(top >=100) {
        header.classList.add('navbarDark');
    }
    else {
        header.classList.remove('navbarDark');
    }
}

Now, let's break down the above code:

  • The header holds the value of the nav element since the querySelector method returns the first element that matches the CSS selector (which is .navbar in this case).
  • window.onscroll fires up when the scroll event happens.
  • window.scrollY returns the number of pixels that the document is scrolled vertically and its value is assigned to a variable named top.
  • If the value of top is greater than or equal to 100, it adds a class of navbarDark to the header.

Let's quickly add CSS for the navbarDark class. For that, go to your style.css file and add the following code:

/* display background color black on navbar scroll */
.navbarScroll.navbarDark {
    background-color: black;
}

This is how the navbar will look now:

navbar

Dark background color on Navbar on page scroll

How to Build the Portfolio Section

This section includes your best work. People can see what you are capable of doing, and showcasing strong past work will definitely attract more potential clients or recruiters. So only add your best work in this section.

We will use Bootstrap cards to display the portfolio projects. There will be 2 rows and each row will have 3 columns of cards.

This will be the code for portfolio section:

<!-- portfolio section-->
    <section id="portfolio">
        <div class="container mt-3">
            <h1 class="text-center">Portfolio</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">YouTube Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Quiz App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage3.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Product Landing Page</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <br>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Messaging Service</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Twitter Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Blog App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
    </section>

Each card has an image, title, description, and link to the projects. Three cards are displayed in a row for large screens which have breakpoints of ≥ 992px wide, but for screens < 992px wide only a single card is displayed in a row.

The GIF below shows how the portfolio section looks now:

portfolio

Portfolio

How to Build the Contact Section

You should include your contact information in this section so that visitors can contact you if they want to hire you.

Our contact section will include 2 columns in a single row: Google maps for location and a contact form.

In order to embed the Google map, you need to follow these steps:

  • go to https://www.embed-map.com
  • enter your location
  • click on the Generate HTML Code button which will provide your Google Map HTML Code

Our code will look like this with the contact form included:

<!-- contact section-->
    <section id="contact">
        <div class="container mt-3 contactContent">
            <h1 class="text-center">Contact Me</h1>

            <div class="row mt-4">
                <div class="col-lg-6">
                    <!-- to edit google map goto https://www.embed-map.com type your location, generate html code and copy the html  -->
                    <div style="max-width:100%;overflow:hidden;color:red;width:500px;height:500px;">
                        <div id="embedmap-canvas" style="height:100%; width:100%;max-width:100%;">
                            <iframe style="height:100%;width:100%;border:0;" frameborder="0" src="https://www.google.com/maps/embed/v1/place?q=new+york&key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8">
                            </iframe>
                        </div>
                        <a class="googlemaps-html" href="https://www.embed-map.com" id="get-data-forembedmap">https://www.embed-map.com</a>
                        <style>#embedmap-canvas img{max-width:none!important;background:none!important;font-size: inherit;font-weight:inherit;}
                        </style>
                    </div>
                </div>

                <div class="col-lg-6">
                    <!-- form fields -->
                    <form>
                        <input type="text" class="form-control form-control-lg" placeholder="Name">
                        <input type="email" class="form-control mt-3" placeholder="Email">
                        <input type="text" class="form-control mt-3" placeholder="Subject">
                        <div class="mb-3 mt-3">
                            <textarea class="form-control" rows="5" id="comment" name="text" placeholder="Project Details"></textarea>
                        </div>
                    </form>
                    <button type="button" class="btn btn-success mt-3">Contact Me</button>
                    
                </div>

            </div>
        </div>
    </section>

The first column will display the Google map and the next one will display the contact form.

The form has four different form fields: name, email, subject and project details. The form doesn't submit the request itself. You will need to connect it with any back-end language. Or, you can simply use Netlify Form or Formspree form for this.

This is how the contact section will appear:

Screenshot-from-2022-01-25-11-31-56

Contact Section

How to Build the Footer Section

Now we have come to the last section of this post, which is the footer section. We have already added a link to the font awesome CDN in the index.html file.

In the Footer, we will add links to our social media through font awesome icons.

 <!-- footer section-->
    <footer id="footer">
        <div class="container-fluid">
            <!-- social media icons -->
            <div class="social-icons mt-4">
                <a href="https://www.facebook.com/" target="_blank"><i class="fab fa-facebook"></i></a>
                <a href="https://www.instagram.com/" target="_blank"><i class="fab fa-instagram"></i></a>
                <a href="https://www.twitter.com/" target="_blank"><i class="fab fa-twitter"></i></a>
                <a href="https://www.linkedin.com/" target="_blank"><i class="fab fa-linkedin"></i></a>
                <a href="https://www.twitch.tv/" target="_blank"><i class="fab fa-twitch"></i></a>
            </div>
        </div>
    </footer>

Without the CSS, our footer will look like this:

Screenshot-from-2022-01-23-17-56-37

footer without styling

So let's add some styling to the footer with this code:

/* social media icons styling */
.social-icons {
    font-size: 36px;
    cursor: pointer;
}
.fa-facebook:hover,.fa-instagram:hover,.fa-twitter:hover,.fa-linkedin:hover, .fa-twitch:hover {
    color: #008000;
}
.fab {
    color: #000000;
}
/* footer styling */
#footer {
    background-color: #808080;
    text-align: center;
}

The icons are now displayed in the center with a hover effect which we can see in the below GIF file.

footer

Footer

Final Touches

In order to add some spacing between all the sections, let's add some more styling:

/* spacing on all sections */
#about, #services, #portfolio, #contact {
    margin-top: 4rem;
    padding-top: 4rem;
}
#contact {
    padding-bottom: 4rem;
}

Now we're done making our complete portfolio website.

You can find the full source code of this project here.

Conclusion

This is how you can create a complete responsive portfolio website using HTML, CSS, JavaScript, and Bootstrap 5 .

In this blog post we saw some of the benefits of creating a portfolio website for web developers and designers. We divided the whole website into different sections and discussed each one individually as we built it.

You can customize this website based on your own use cases.

I hope you found this post useful.

Happy Coding!

Original article source at https://www.freecodecamp.org

#webdesign #webdevelopment #css #html #javascript #programming #webdev 

How to Create Your Own Portfolio Website with HTML, CSS & JavaScript
Web  Dev

Web Dev

1650349069

Create a Responsive Portfolio Website with HTML, CSS, JavaScript & Bootstrap 5

If you are a web developer or a web designer, it is essential for you to have a portfolio website. It lets you provide information about yourself and showcase your best work with your relevant skills and experience.

In this blog post, I will discuss some of the benefits of creating a portfolio website. Then I'll show you how to create a beautiful responsive portfolio website for yourself using HTML, CSS, JavaScript and Bootstrap version 5.

Table Of Contents

  • Benefits of having a portfolio website
  • What is Bootstrap?
  • Folder Structure
  • How to Add a Navigation Menu to Your Portfolio
  • How to Add a Hero Header to the Portfolio
  • How to Make the About Section
  • How to Make the Services Section
  • How to Add Dark Background Color to Navbar on Page Scroll
  • How to Build the Portfolio Section
  • How to Build the Contact Section
  • How to Build the Footer Section
  • Adding Final Touches
  • Conclusion

Benefits of having a Portfolio Website

Having a portfolio website has several benefits, including:

  • it provides a platform to showcase your relevant skills and experience
  • it shows your personality
  • it lets hiring managers find you instead of you reaching out to them
  • you are easily searchable on search engines like Google

What is Bootstrap?

Bootstrap is a popular front-end CSS framework which is used to develop responsive and mobile friendly websites. The latest release of Bootstrap is version 5. You can find the official documentation of Bootstrap 5 here.

Folder Structure

We will now start working on creating the portfolio website.

First, let's create the folder structure. You can get the project starter files on GitHub. Also, you can visit here to see the live demo of this project.

Screenshot-from-2022-01-22-19-10-25

Project Folder Structure

The folder structure consists of index.html, style.css, and script.js files and an images folder. We'll write all CSS in the style.css file and the JavaScript in the script.js file .

In the index.html file, you can see the HTML boilerplate code with the Bootstrap CDN, font awesome kit, and a link to the external style sheet and JavaScript.

Here, the script.js file is loaded after loading all the HTML code.

How to Add a Navigation Menu to Your Portfolio

Now, let's work on adding a navigation menu in our project. It will help visitors find the relevant info they're looking for.

We will use Bootstrap's fixed-top class in nav element to keep the navbar at the top of the page. The navbar also has a navbar-brand class where we keep the name of the person as a brand.

<nav class="navbar navbar-expand-lg fixed-top navbarScroll">
        <div class="container">
            <a class="navbar-brand" href="#">Brad</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item active">
                        <a class="nav-link" href="#home">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#about">About</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#services">Services</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#portfolio">Portfolio</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#contact">Contact</a>
                    </li>
                </ul>
                
            </div>
        </div>
    </nav>

The navbar has the following features:

  • It has six links: home, about, services, portfolio, contact, and footer
  • It has a transparent background. We will add a dark background on page scrolling later.
  • It toggles on smaller devices

You can find more details regarding Bootstrap 5 navbar features here.

However, the navbar has a problem while scrolling. It's fully transparent throughout the page which causes readability issues.  We will fix this issue after we complete the Services section to make you understand the issue properly.

How to Add a Hero Header to the Portfolio

Now, we will be adding a hero image with some text in the center. A hero image is a web design term which refers to a high quality full width image that displays the company or individual's main goals, a representative image, photo, or other eye-catching elements. It helps attract users to your site.

 <!-- main banner -->
    <section class="bgimage" id="home">
        <div class="container-fluid">
            <div class="row">
            <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 hero-text">
                <h2 class="hero_title">Hi, it's me Brad</h2>
                <p class="hero_desc">I am a professional freelancer in New York City</p>
            </div>
            </div>
        </div>
    </section>

 Also, let's add the CSS for the above code in the style.css file:

/* hero background image */
.bgimage {
    height:100vh;
    background: url('images/heroImage.jpeg');
    background-size:cover;
    position:relative;
}
/* text css above hero image*/
.hero_title {
    font-size: 4.5rem;
}
.hero_desc {
    font-size: 2rem;
}
.hero-text {
    text-align: center;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: white;
}

Here we can see that the section has an id named bgimage which is responsible for displaying the background hero image with full width. It also displays some text in the center above the background image with the help of the above CSS.

This is how the site looks so far with the navbar and the hero section:

Screenshot-from-2022-01-25-10-13-25

Hero Image with Navbar

How to Make the About Section

The About page contains important information about you and your background. Visitors to your portfolio site can get to know you through the information you provide in this page.

We will be adding an image to the left side of the row, and on the right side we will add our quick introduction in this section. Let's demonstrate it using the code below:

<!-- about section-->
    <section id="about">
        <div class="container mt-4 pt-4">
            <h1 class="text-center">About Me</h1>
            <div class="row mt-4">
                <div class="col-lg-4">
                    <img src="images/about.jpeg" class= "imageAboutPage" alt="">
                </div>

                <div class="col-lg-8">
                    <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged
                        
                    </p>
                    <div class="row mt-3">
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                    </div>
                    <div class="row mt-3">
                        <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                            Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                        </p>
                    </div>
                </div>
            </div>
    </section>

Let's add some CSS for the left side image:

/* about section image css */
.imageAboutPage {
    width: 100%;
}

This will create an about section. You can modify the content based on your use cases. We have added classes named mt-4 and pt-4 with container class which will set the margin top and padding top to 1.5 rem.

The row has two columns. One has the col-lg-4 class for displaying the image which will occupy the left column with a 4-part grid for large screens.

The next column is assigned a class of col-lg-8 which will occupy the right column with an 8-part grid for larger screens. For medium and small screens they will overlap with each other which we can see in the below GIF file:

about

About Section

How to Make the Services Section

This section helps convert website visitors into potential clients. This is where you explain what specific services you offer, and where you niche down your offered services.

Let's add the code for this section and describe it below:

<!-- services section-->
    <section id="services">
        <div class="container">
            <h1 class="text-center">Services</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class="fas servicesIcon fa-clock"></i>
                            <h4 class="card-title mt-3">Website Development</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-layer-group'></i>
                            <h4 class="card-title mt-3">Website Design</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='far servicesIcon fa-check-circle'></i>
                            <h4 class="card-title mt-3">Website Deployment</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>

            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-search'></i>
                            <h4 class="card-title mt-3">SEO</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-shield-alt'></i>
                            <h4 class="card-title mt-3">DevOps</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-wrench'></i>
                            <h4 class="card-title mt-3">QA</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>
        </div>
    </section>

Since this website is targeted towards web developers and designers, I've included some of the services which a web developer or designer might offer.

We have used bootstrap cards to display services. Our services section has 2 rows and 3 columns each. For large screens with a width greater than or equal to 992px, three cards are displayed in a row. For screens less than 992px wide, only a single card is displayed in a row.

You can find more about bootstrap breakpoints here.

Also, there are fonts added in each card to make them look better.

Without CSS, the services section would look like this :

Screenshot-from-2022-01-23-14-01-00

So, let's add some CSS to increase the font icon font size and card height and add some extra color when a user hovers over a card.

/* services section css */
.servicesText.card {
    height: 280px;
    cursor: pointer;
  }
.servicesIcon {
    font-size: 36px;
    text-align: center;
    width: 100%;
}
.card-title {
    text-align: center;
}
.card:hover .servicesIcon {
    color: #008000;
}
.servicesText:hover {
    border: 1px solid #008000;
}

This is how our services section looks now:

services

Services 

How to Add Dark Background Color to Navbar on Page Scroll

If you look into the above gif properly you will see that the navbar is transparent throughout the page which causes readability issues. So let's work on fixing this issue.

We will write some JavaScript and CSS in order to resolve this problem. We will add a navbarDark class in order to show a dark background color for the navbar on page scroll.

For that we need to go to the script.js file and add the following code:

// add class navbarDark on navbar scroll
const header = document.querySelector('.navbar');

window.onscroll = function() {
    var top = window.scrollY;
    if(top >=100) {
        header.classList.add('navbarDark');
    }
    else {
        header.classList.remove('navbarDark');
    }
}

Now, let's break down the above code:

  • The header holds the value of the nav element since the querySelector method returns the first element that matches the CSS selector (which is .navbar in this case).
  • window.onscroll fires up when the scroll event happens.
  • window.scrollY returns the number of pixels that the document is scrolled vertically and its value is assigned to a variable named top.
  • If the value of top is greater than or equal to 100, it adds a class of navbarDark to the header.

Let's quickly add CSS for the navbarDark class. For that, go to your style.css file and add the following code:

/* display background color black on navbar scroll */
.navbarScroll.navbarDark {
    background-color: black;
}

This is how the navbar will look now:

navbar

Dark background color on Navbar on page scroll

How to Build the Portfolio Section

This section includes your best work. People can see what you are capable of doing, and showcasing strong past work will definitely attract more potential clients or recruiters. So only add your best work in this section.

We will use Bootstrap cards to display the portfolio projects. There will be 2 rows and each row will have 3 columns of cards.

This will be the code for portfolio section:

<!-- portfolio section-->
    <section id="portfolio">
        <div class="container mt-3">
            <h1 class="text-center">Portfolio</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">YouTube Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Quiz App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage3.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Product Landing Page</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <br>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Messaging Service</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Twitter Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Blog App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
    </section>

Each card has an image, title, description, and link to the projects. Three cards are displayed in a row for large screens which have breakpoints of ≥ 992px wide, but for screens < 992px wide only a single card is displayed in a row.

The GIF below shows how the portfolio section looks now:

portfolio

Portfolio

How to Build the Contact Section

You should include your contact information in this section so that visitors can contact you if they want to hire you.

Our contact section will include 2 columns in a single row: Google maps for location and a contact form.

In order to embed the Google map, you need to follow these steps:

  • go to https://www.embed-map.com
  • enter your location
  • click on the Generate HTML Code button which will provide your Google Map HTML Code

Our code will look like this with the contact form included:

<!-- contact section-->
    <section id="contact">
        <div class="container mt-3 contactContent">
            <h1 class="text-center">Contact Me</h1>

            <div class="row mt-4">
                <div class="col-lg-6">
                    <!-- to edit google map goto https://www.embed-map.com type your location, generate html code and copy the html  -->
                    <div style="max-width:100%;overflow:hidden;color:red;width:500px;height:500px;">
                        <div id="embedmap-canvas" style="height:100%; width:100%;max-width:100%;">
                            <iframe style="height:100%;width:100%;border:0;" frameborder="0" src="https://www.google.com/maps/embed/v1/place?q=new+york&key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8">
                            </iframe>
                        </div>
                        <a class="googlemaps-html" href="https://www.embed-map.com" id="get-data-forembedmap">https://www.embed-map.com</a>
                        <style>#embedmap-canvas img{max-width:none!important;background:none!important;font-size: inherit;font-weight:inherit;}
                        </style>
                    </div>
                </div>

                <div class="col-lg-6">
                    <!-- form fields -->
                    <form>
                        <input type="text" class="form-control form-control-lg" placeholder="Name">
                        <input type="email" class="form-control mt-3" placeholder="Email">
                        <input type="text" class="form-control mt-3" placeholder="Subject">
                        <div class="mb-3 mt-3">
                            <textarea class="form-control" rows="5" id="comment" name="text" placeholder="Project Details"></textarea>
                        </div>
                    </form>
                    <button type="button" class="btn btn-success mt-3">Contact Me</button>
                    
                </div>

            </div>
        </div>
    </section>

The first column will display the Google map and the next one will display the contact form.

The form has four different form fields: name, email, subject and project details. The form doesn't submit the request itself. You will need to connect it with any back-end language. Or, you can simply use Netlify Form or Formspree form for this.

This is how the contact section will appear:

Screenshot-from-2022-01-25-11-31-56

Contact Section

How to Build the Footer Section

Now we have come to the last section of this post, which is the footer section. We have already added a link to the font awesome CDN in the index.html file.

In the Footer, we will add links to our social media through font awesome icons.

 <!-- footer section-->
    <footer id="footer">
        <div class="container-fluid">
            <!-- social media icons -->
            <div class="social-icons mt-4">
                <a href="https://www.facebook.com/" target="_blank"><i class="fab fa-facebook"></i></a>
                <a href="https://www.instagram.com/" target="_blank"><i class="fab fa-instagram"></i></a>
                <a href="https://www.twitter.com/" target="_blank"><i class="fab fa-twitter"></i></a>
                <a href="https://www.linkedin.com/" target="_blank"><i class="fab fa-linkedin"></i></a>
                <a href="https://www.twitch.tv/" target="_blank"><i class="fab fa-twitch"></i></a>
            </div>
        </div>
    </footer>

Without the CSS, our footer will look like this:

Screenshot-from-2022-01-23-17-56-37

footer without styling

So let's add some styling to the footer with this code:

/* social media icons styling */
.social-icons {
    font-size: 36px;
    cursor: pointer;
}
.fa-facebook:hover,.fa-instagram:hover,.fa-twitter:hover,.fa-linkedin:hover, .fa-twitch:hover {
    color: #008000;
}
.fab {
    color: #000000;
}
/* footer styling */
#footer {
    background-color: #808080;
    text-align: center;
}

The icons are now displayed in the center with a hover effect which we can see in the below GIF file.

footer

Footer

Final Touches

In order to add some spacing between all the sections, let's add some more styling:

/* spacing on all sections */
#about, #services, #portfolio, #contact {
    margin-top: 4rem;
    padding-top: 4rem;
}
#contact {
    padding-bottom: 4rem;
}

Now we're done making our complete portfolio website.

You can find the full source code of this project here.

Conclusion

This is how you can create a complete responsive portfolio website using HTML, CSS, JavaScript, and Bootstrap 5 .

In this blog post we saw some of the benefits of creating a portfolio website for web developers and designers. We divided the whole website into different sections and discussed each one individually as we built it.

You can customize this website based on your own use cases.

I hope you found this post useful.

Happy Coding!

Original article source at https://www.freecodecamp.org

#html #css #javascript #bootstrap #webdev #programming

Create a Responsive Portfolio Website with HTML, CSS, JavaScript & Bootstrap 5

KarserRecaptcha3Bundle: Google ReCAPTCHA V3 for Symfony

KarserRecaptcha3Bundle

reCAPTCHA v3 returns a score for each request without user friction. The score is based on interactions with your site (1.0 is very likely a good interaction, 0.0 is very likely a bot) and enables you to take an appropriate action for your site. Register reCAPTCHA v3 keys here.

image

Installation

With composer, require:

composer require karser/karser-recaptcha3-bundle

You can quickly configure this bundle by using symfony/flex:

  • answer no for google/recaptcha
  • answer yes for karser/karser-recaptcha3-bundle image

Configuration without symfony/flex:

1. Register the bundle

Symfony 4/5/6 Version :
Register bundle into config/bundles.php:

return [
    //...
    Karser\Recaptcha3Bundle\KarserRecaptcha3Bundle::class => ['all' => true],
];

Symfony 3 Version:
Register bundle into app/AppKernel.php:

public function registerBundles()
{
    return array(
        // ...
        new Karser\Recaptcha3Bundle\KarserRecaptcha3Bundle(),
    );
}

2. Add configuration files

# config/packages/karser_recaptcha3.yaml (or app/config/config.yml if using Symfony3)

karser_recaptcha3:
    site_key: '%env(RECAPTCHA3_KEY)%'
    secret_key: '%env(RECAPTCHA3_SECRET)%'
    score_threshold: 0.5

Add your site key and secret to your .env file:

###> karser/recaptcha3-bundle ###
RECAPTCHA3_KEY=my_site_key
RECAPTCHA3_SECRET=my_secret
###< karser/recaptcha3-bundle ###

Usage

How to integrate re-captcha in Symfony form:

<?php

use Karser\Recaptcha3Bundle\Form\Recaptcha3Type;
use Karser\Recaptcha3Bundle\Validator\Constraints\Recaptcha3;

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('captcha', Recaptcha3Type::class, [
            'constraints' => new Recaptcha3(),
            'action_name' => 'homepage',
            'script_nonce_csp' => $nonceCSP,
        ]);
    }
}

Notes:

  • The action_name parameter is reCAPTCHA v3 action which identifies the submission of this particular form in the Google reCAPTCHA dashboard, and confirming it is as expected in the backend is a recommended extra security step.
  • The script_nonce_csp parameter is optional. You must use the same nonce as in your Content-Security Policy header.

How to use reCAPTCHA globally (meaning even in China):

Use 'www.recaptcha.net' host in your code when 'www.google.com' is not accessible.

# config/packages/karser_recaptcha3.yaml (or app/config/config.yml if using Symfony3)

karser_recaptcha3:
    host: 'www.recaptcha.net' # default is 'www.google.com'

How can I set the captcha language for different locales?

You should install the Symfony Translation component. Then replace the validation text with the translation keys for the message and messageMissingValue options:

$builder->add('captcha', Recaptcha3Type::class, [
     'constraints' => new Recaptcha3 ([
         'message' => 'karser_recaptcha3.message',
         'messageMissingValue' => 'karser_recaptcha3.message_missing_value',
     ]),
]);

Add English, Spanish, or any other translation:

# translations/validators/validators.en.yaml
karser_recaptcha3.message: 'Your computer or network may be sending automated queries'
karser_recaptcha3.message_missing_value: 'The captcha value is missing'

# translations/validators/validators.es.yaml
karser_recaptcha3.message: 'Es posible que su computadora o red esté enviando consultas automatizadas'
karser_recaptcha3.message_missing_value: 'Falta el valor de captcha'

How to get the ReCaptcha score:

Inject the Recaptcha3Validator and call getLastResponse()->getScore() after the form was submitted:

<?php

use Karser\Recaptcha3Bundle\Validator\Constraints\Recaptcha3Validator;

class TaskController extends AbstractController
{
    public function new(Request $request, Recaptcha3Validator $recaptcha3Validator): Response
    {
        //...
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            //...
            $score = $recaptcha3Validator->getLastResponse()->getScore();
            //...
        }
        //...
    }
}

How to integrate re-captcha in API method:

The idea is to require the frontend to submit the captcha token, so it will be validated on server side.

First you need to add the captcha field to your transport entity:

<?php

namespace App\Dto;

final class UserSignupRequest
{
    /** @var string|null */
    public $email;

    /** @var string|null */
    public $captcha;
}

And to add the validation constraint:

#config/validator/validation.yaml
App\Dto\UserSignupRequest:
    properties:
        email:
            - NotBlank: ~
            - Email: { mode: strict }
        captcha:
            - Karser\Recaptcha3Bundle\Validator\Constraints\Recaptcha3: ~

On frontend part you need to submit the captcha token along with email. You can obtain the captcha token either on page load or on form submit.

<script src="https://www.google.com/recaptcha/api.js?render=<siteKey>"></script>

<script>
const siteKey = '*****************-**-******-******';

//either on page load
grecaptcha.ready(function() {
    grecaptcha.execute(siteKey, {
        action: 'homepage'
    }).then(function(token) {
        //the token will be sent on form submit
        $('[name="captcha"]').val(token);
        //keep in mind that token expires in 120 seconds so it's better to add setTimeout.
    });
});

//or on form post:
grecaptcha.ready(function() {
    grecaptcha.execute(siteKey, {
        action: 'homepage'
    }).then(function(token) {
        //submit the form
        return http.post(url, {email, captcha: token});
    });
});
</script>

How to show errors from the captcha's response

Just add the {{ errorCodes }} variable to the message template:

$formBuilder->add('captcha', Recaptcha3Type::class, [
    'constraints' => new Recaptcha3(['message' => 'There were problems with your captcha. Please try again or contact with support and provide following code(s): {{ errorCodes }}']),
])

How to deal with functional and e2e testing:

Recaptcha won't allow you to test your app efficiently unless you disable it for the environment you are testing against.

# app/config/config.yml (or config/packages/karser_recaptcha3.yaml if using Symfony4)
karser_recaptcha3:
    enabled: '%env(bool:RECAPTCHA3_ENABLED)%'
#.env.test or an environment variable
RECAPTCHA3_ENABLED=0

How to set the threshold from PHP dynamically rather from the .yaml config or .env?

You should inject @karser_recaptcha3.google.recaptcha in your service and call setScoreThreshold method.

#services.yaml
App\Services\YourService:
    arguments: ['@karser_recaptcha3.google.recaptcha']
#App/Services/YourService.php

use ReCaptcha\ReCaptcha;

class YourService {
    private $reCaptcha;

    public function __construct(ReCaptcha $reCaptcha) {
        $this->reCaptcha = $reCaptcha;
    }

    public function yourMethod() {
        $this->reCaptcha->setScoreThreshold(0.7);
    }
}

How to resolve IP propertly when behind Cloudflare:

From the Cloudflare docs: To provide the client (visitor) IP address for every request to the origin, Cloudflare adds the CF-Connecting-IP header.

"CF-Connecting-IP: A.B.C.D"

So you can implement custom IP resolver which attempts to read the CF-Connecting-IP header or fallbacks with the internal IP resolver:

<?php declare(strict_types=1);

namespace App\Service;

use Karser\Recaptcha3Bundle\Services\IpResolverInterface;
use Symfony\Component\HttpFoundation\RequestStack;

class CloudflareIpResolver implements IpResolverInterface
{
    /** @var IpResolverInterface */
    private $decorated;

    /** @var RequestStack */
    private $requestStack;

    public function __construct(IpResolverInterface $decorated, RequestStack $requestStack)
    {
        $this->decorated = $decorated;
        $this->requestStack = $requestStack;
    }

    public function resolveIp(): ?string
    {
        return $this->doResolveIp() ?? $this->decorated->resolveIp();
    }

    private function doResolveIp(): ?string
    {
        $request = $this->requestStack->getCurrentRequest();
        if ($request === null) {
            return null;
        }
        return $request->server->get('HTTP_CF_CONNECTING_IP');
    }
}

Here is the service declaration. It decorates the internal resolver:

#services.yaml
services:
    App\Service\CloudflareIpResolver:
        decorates: 'karser_recaptcha3.ip_resolver'
        arguments:
            $decorated: '@App\Service\CloudflareIpResolver.inner'
            $requestStack: '@request_stack'

Troubleshooting checklist

Make sure you setup recaptcha key/secret of version 3.

Also, make sure you added the domain you use in the recaptcha settings. Usually dev domain differs from the production one, so better to double check. image

Make sure you are seeing this in the html of your rendered form

<input type="hidden" id="form_captcha" name="form[captcha]" /><script>
    var recaptchaCallback_form_captcha = function() {
    grecaptcha.execute('<YOUR-RECAPTCHA-KEY>', {action: 'landing'}).then(function(token) {
    document.getElementById('form_captcha').value = token;
    });
    };
    </script><script src="https://www.google.com/recaptcha/api.js?render=<YOUR-RECAPTCHA-KEY>&onload=recaptchaCallback_form_captcha" async defer></script> 
</form>

Make sure you don't have javascript errors in the browser console

Testing

composer update
vendor/bin/phpunit

Author: Karser
Source Code: https://github.com/karser/KarserRecaptcha3Bundle 
License: MIT License

#php #symfony #recaptcha 

KarserRecaptcha3Bundle: Google ReCAPTCHA V3 for Symfony
Coding  Fan

Coding Fan

1648019674

The Most Important AWS Core Services That You Need To Know About!

If you're looking to understand the wide variety of AWS services, this is the video for you. In this video, I explain to you the core AWS services through an easy to follow example. We explore services such as Amazon S3, AWS Lambda, Amazon RDS, DynamoDB, and many more!

01:35 Website Hosting
03:05 Domain Registration
03:25 API Hosting
07:19 Databases
10:42 Application Orchestration
10:47 Analytics, BigData, ML
13:26 Security
16:04 Monitoring

☁Topics covered include:
Cloudfront
S3
Route 53
API Gateway
Load Balancer
AWS Lambda
EC2
ECS
VPC
IAM
Cloudwatch
Cloudtrail
SNS
SQS
Step Functions
RDS
Redshift
DynamoDB
Neptune
Elasticache
Athena
EMR
Quicksight
Sagemaker

Subscribe: https://www.youtube.com/c/BeABetterDev/featured 

#aws #services 

The Most Important AWS Core Services That You Need To Know About!
Web  Dev

Web Dev

1645673869

Responsive Portfolio Website using HTML, CSS, JavaScript and Bootstrap 5

How to Create a Portfolio Website Using HTML, CSS, JavaScript, and Bootstrap 5

If you are a web developer or a web designer, it is essential for you to have a portfolio website. It lets you provide information about yourself and showcase your best work with your relevant skills and experience.

In this blog post, I will discuss some of the benefits of creating a portfolio website. Then I'll show you how to create a beautiful responsive portfolio website for yourself using HTML, CSS, JavaScript and Bootstrap version 5.

Table Of Contents

  • Benefits of having a portfolio website
  • What is Bootstrap?
  • Folder Structure
  • How to Add a Navigation Menu to Your Portfolio
  • How to Add a Hero Header to the Portfolio
  • How to Make the About Section
  • How to Make the Services Section
  • How to Add Dark Background Color to Navbar on Page Scroll
  • How to Build the Portfolio Section
  • How to Build the Contact Section
  • How to Build the Footer Section
  • Adding Final Touches
  • Conclusion

Benefits of having a Portfolio Website

Having a portfolio website has several benefits, including:

  • it provides a platform to showcase your relevant skills and experience
  • it shows your personality
  • it lets hiring managers find you instead of you reaching out to them
  • you are easily searchable on search engines like Google

What is Bootstrap?

Bootstrap is a popular front-end CSS framework which is used to develop responsive and mobile friendly websites. The latest release of Bootstrap is version 5. You can find the official documentation of Bootstrap 5 here.

Folder Structure

We will now start working on creating the portfolio website.

First, let's create the folder structure. You can get the project starter files on GitHub. Also, you can visit here to see the live demo of this project.

Screenshot-from-2022-01-22-19-10-25

Project Folder Structure

The folder structure consists of index.html, style.css, and script.js files and an images folder. We'll write all CSS in the style.css file and the JavaScript in the script.js file .

In the index.html file, you can see the HTML boilerplate code with the Bootstrap CDN, font awesome kit, and a link to the external style sheet and JavaScript.

Here, the script.js file is loaded after loading all the HTML code.

How to Add a Navigation Menu to Your Portfolio

Now, let's work on adding a navigation menu in our project. It will help visitors find the relevant info they're looking for.

We will use Bootstrap's fixed-top class in nav element to keep the navbar at the top of the page. The navbar also has a navbar-brand class where we keep the name of the person as a brand.

<nav class="navbar navbar-expand-lg fixed-top navbarScroll">
        <div class="container">
            <a class="navbar-brand" href="#">Brad</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item active">
                        <a class="nav-link" href="#home">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#about">About</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#services">Services</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#portfolio">Portfolio</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#contact">Contact</a>
                    </li>
                </ul>
                
            </div>
        </div>
    </nav>

The navbar has the following features:

  • It has six links: home, about, services, portfolio, contact, and footer
  • It has a transparent background. We will add a dark background on page scrolling later.
  • It toggles on smaller devices

You can find more details regarding Bootstrap 5 navbar features here.

However, the navbar has a problem while scrolling. It's fully transparent throughout the page which causes readability issues.  We will fix this issue after we complete the Services section to make you understand the issue properly.

How to Add a Hero Header to the Portfolio

Now, we will be adding a hero image with some text in the center. A hero image is a web design term which refers to a high quality full width image that displays the company or individual's main goals, a representative image, photo, or other eye-catching elements. It helps attract users to your site.

 <!-- main banner -->
    <section class="bgimage" id="home">
        <div class="container-fluid">
            <div class="row">
            <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 hero-text">
                <h2 class="hero_title">Hi, it's me Brad</h2>
                <p class="hero_desc">I am a professional freelancer in New York City</p>
            </div>
            </div>
        </div>
    </section>

 Also, let's add the CSS for the above code in the style.css file:

/* hero background image */
.bgimage {
    height:100vh;
    background: url('images/heroImage.jpeg');
    background-size:cover;
    position:relative;
}
/* text css above hero image*/
.hero_title {
    font-size: 4.5rem;
}
.hero_desc {
    font-size: 2rem;
}
.hero-text {
    text-align: center;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: white;
}

Here we can see that the section has an id named bgimage which is responsible for displaying the background hero image with full width. It also displays some text in the center above the background image with the help of the above CSS.

This is how the site looks so far with the navbar and the hero section:

Screenshot-from-2022-01-25-10-13-25

Hero Image with Navbar

How to Make the About Section

The About page contains important information about you and your background. Visitors to your portfolio site can get to know you through the information you provide in this page.

We will be adding an image to the left side of the row, and on the right side we will add our quick introduction in this section. Let's demonstrate it using the code below:

<!-- about section-->
    <section id="about">
        <div class="container mt-4 pt-4">
            <h1 class="text-center">About Me</h1>
            <div class="row mt-4">
                <div class="col-lg-4">
                    <img src="images/about.jpeg" class= "imageAboutPage" alt="">
                </div>

                <div class="col-lg-8">
                    <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged
                        
                    </p>
                    <div class="row mt-3">
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                    </div>
                    <div class="row mt-3">
                        <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                            Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                        </p>
                    </div>
                </div>
            </div>
    </section>

Let's add some CSS for the left side image:

/* about section image css */
.imageAboutPage {
    width: 100%;
}

This will create an about section. You can modify the content based on your use cases. We have added classes named mt-4 and pt-4 with container class which will set the margin top and padding top to 1.5 rem.

The row has two columns. One has the col-lg-4 class for displaying the image which will occupy the left column with a 4-part grid for large screens.

The next column is assigned a class of col-lg-8 which will occupy the right column with an 8-part grid for larger screens. For medium and small screens they will overlap with each other which we can see in the below GIF file:

about

About Section

How to Make the Services Section

This section helps convert website visitors into potential clients. This is where you explain what specific services you offer, and where you niche down your offered services.

Let's add the code for this section and describe it below:

<!-- services section-->
    <section id="services">
        <div class="container">
            <h1 class="text-center">Services</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class="fas servicesIcon fa-clock"></i>
                            <h4 class="card-title mt-3">Website Development</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-layer-group'></i>
                            <h4 class="card-title mt-3">Website Design</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='far servicesIcon fa-check-circle'></i>
                            <h4 class="card-title mt-3">Website Deployment</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>

            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-search'></i>
                            <h4 class="card-title mt-3">SEO</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-shield-alt'></i>
                            <h4 class="card-title mt-3">DevOps</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-wrench'></i>
                            <h4 class="card-title mt-3">QA</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>
        </div>
    </section>

Since this website is targeted towards web developers and designers, I've included some of the services which a web developer or designer might offer.

We have used bootstrap cards to display services. Our services section has 2 rows and 3 columns each. For large screens with a width greater than or equal to 992px, three cards are displayed in a row. For screens less than 992px wide, only a single card is displayed in a row.

You can find more about bootstrap breakpoints here.

Also, there are fonts added in each card to make them look better.

Without CSS, the services section would look like this :

Screenshot-from-2022-01-23-14-01-00

So, let's add some CSS to increase the font icon font size and card height and add some extra color when a user hovers over a card.

/* services section css */
.servicesText.card {
    height: 280px;
    cursor: pointer;
  }
.servicesIcon {
    font-size: 36px;
    text-align: center;
    width: 100%;
}
.card-title {
    text-align: center;
}
.card:hover .servicesIcon {
    color: #008000;
}
.servicesText:hover {
    border: 1px solid #008000;
}

This is how our services section looks now:

services

Services 

How to Add Dark Background Color to Navbar on Page Scroll

If you look into the above gif properly you will see that the navbar is transparent throughout the page which causes readability issues. So let's work on fixing this issue.

We will write some JavaScript and CSS in order to resolve this problem. We will add a navbarDark class in order to show a dark background color for the navbar on page scroll.

For that we need to go to the script.js file and add the following code:

// add class navbarDark on navbar scroll
const header = document.querySelector('.navbar');

window.onscroll = function() {
    var top = window.scrollY;
    if(top >=100) {
        header.classList.add('navbarDark');
    }
    else {
        header.classList.remove('navbarDark');
    }
}

Now, let's break down the above code:

  • The header holds the value of the nav element since the querySelector method returns the first element that matches the CSS selector (which is .navbar in this case).
  • window.onscroll fires up when the scroll event happens.
  • window.scrollY returns the number of pixels that the document is scrolled vertically and its value is assigned to a variable named top.
  • If the value of top is greater than or equal to 100, it adds a class of navbarDark to the header.

Let's quickly add CSS for the navbarDark class. For that, go to your style.css file and add the following code:

/* display background color black on navbar scroll */
.navbarScroll.navbarDark {
    background-color: black;
}

This is how the navbar will look now:

navbar

Dark background color on Navbar on page scroll

How to Build the Portfolio Section

This section includes your best work. People can see what you are capable of doing, and showcasing strong past work will definitely attract more potential clients or recruiters. So only add your best work in this section.

We will use Bootstrap cards to display the portfolio projects. There will be 2 rows and each row will have 3 columns of cards.

This will be the code for portfolio section:

<!-- portfolio section-->
    <section id="portfolio">
        <div class="container mt-3">
            <h1 class="text-center">Portfolio</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">YouTube Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Quiz App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage3.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Product Landing Page</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <br>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Messaging Service</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Twitter Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Blog App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
    </section>

Each card has an image, title, description, and link to the projects. Three cards are displayed in a row for large screens which have breakpoints of ≥ 992px wide, but for screens < 992px wide only a single card is displayed in a row.

The GIF below shows how the portfolio section looks now:

portfolio

Portfolio

How to Build the Contact Section

You should include your contact information in this section so that visitors can contact you if they want to hire you.

Our contact section will include 2 columns in a single row: Google maps for location and a contact form.

In order to embed the Google map, you need to follow these steps:

  • go to https://www.embed-map.com
  • enter your location
  • click on the Generate HTML Code button which will provide your Google Map HTML Code

Our code will look like this with the contact form included:

<!-- contact section-->
    <section id="contact">
        <div class="container mt-3 contactContent">
            <h1 class="text-center">Contact Me</h1>

            <div class="row mt-4">
                <div class="col-lg-6">
                    <!-- to edit google map goto https://www.embed-map.com type your location, generate html code and copy the html  -->
                    <div style="max-width:100%;overflow:hidden;color:red;width:500px;height:500px;">
                        <div id="embedmap-canvas" style="height:100%; width:100%;max-width:100%;">
                            <iframe style="height:100%;width:100%;border:0;" frameborder="0" src="https://www.google.com/maps/embed/v1/place?q=new+york&key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8">
                            </iframe>
                        </div>
                        <a class="googlemaps-html" href="https://www.embed-map.com" id="get-data-forembedmap">https://www.embed-map.com</a>
                        <style>#embedmap-canvas img{max-width:none!important;background:none!important;font-size: inherit;font-weight:inherit;}
                        </style>
                    </div>
                </div>

                <div class="col-lg-6">
                    <!-- form fields -->
                    <form>
                        <input type="text" class="form-control form-control-lg" placeholder="Name">
                        <input type="email" class="form-control mt-3" placeholder="Email">
                        <input type="text" class="form-control mt-3" placeholder="Subject">
                        <div class="mb-3 mt-3">
                            <textarea class="form-control" rows="5" id="comment" name="text" placeholder="Project Details"></textarea>
                        </div>
                    </form>
                    <button type="button" class="btn btn-success mt-3">Contact Me</button>
                    
                </div>

            </div>
        </div>
    </section>

The first column will display the Google map and the next one will display the contact form.

The form has four different form fields: name, email, subject and project details. The form doesn't submit the request itself. You will need to connect it with any back-end language. Or, you can simply use Netlify Form or Formspree form for this.

This is how the contact section will appear:

Screenshot-from-2022-01-25-11-31-56

Contact Section

How to Build the Footer Section

Now we have come to the last section of this post, which is the footer section. We have already added a link to the font awesome CDN in the index.html file.

In the Footer, we will add links to our social media through font awesome icons.

 <!-- footer section-->
    <footer id="footer">
        <div class="container-fluid">
            <!-- social media icons -->
            <div class="social-icons mt-4">
                <a href="https://www.facebook.com/" target="_blank"><i class="fab fa-facebook"></i></a>
                <a href="https://www.instagram.com/" target="_blank"><i class="fab fa-instagram"></i></a>
                <a href="https://www.twitter.com/" target="_blank"><i class="fab fa-twitter"></i></a>
                <a href="https://www.linkedin.com/" target="_blank"><i class="fab fa-linkedin"></i></a>
                <a href="https://www.twitch.tv/" target="_blank"><i class="fab fa-twitch"></i></a>
            </div>
        </div>
    </footer>

Without the CSS, our footer will look like this:

Screenshot-from-2022-01-23-17-56-37

footer without styling

So let's add some styling to the footer with this code:

/* social media icons styling */
.social-icons {
    font-size: 36px;
    cursor: pointer;
}
.fa-facebook:hover,.fa-instagram:hover,.fa-twitter:hover,.fa-linkedin:hover, .fa-twitch:hover {
    color: #008000;
}
.fab {
    color: #000000;
}
/* footer styling */
#footer {
    background-color: #808080;
    text-align: center;
}

The icons are now displayed in the center with a hover effect which we can see in the below GIF file.

footer

Footer

Final Touches

In order to add some spacing between all the sections, let's add some more styling:

/* spacing on all sections */
#about, #services, #portfolio, #contact {
    margin-top: 4rem;
    padding-top: 4rem;
}
#contact {
    padding-bottom: 4rem;
}

Now we're done making our complete portfolio website.

You can find the full source code of this project here.

Conclusion

This is how you can create a complete responsive portfolio website using HTML, CSS, JavaScript, and Bootstrap 5 .

In this blog post we saw some of the benefits of creating a portfolio website for web developers and designers. We divided the whole website into different sections and discussed each one individually as we built it.

You can customize this website based on your own use cases.

I hope you found this post useful.

Happy Coding!

Original article source at https://www.freecodecamp.org

#html #css #javascript #express #bootstrap #webdev

Responsive Portfolio Website using HTML, CSS, JavaScript and Bootstrap 5

Keyring: Store and Access Your Passwords Safely

The Python keyring library provides an easy way to access the system keyring service from python. It can be used in any application that needs safe password storage.

These recommended keyring backends are supported:

Other keyring implementations are available through Third-Party Backends.

Installation - Linux

On Linux, the KWallet backend relies on dbus-python, which does not always install correctly when using pip (compilation is needed). For best results, install dbus-python as a system package.

Compatibility - macOS

macOS keychain support macOS 11 (Big Sur) and later requires Python 3.8.7 or later with the "universal2" binary. See #525 for details.

Using Keyring

The basic usage of keyring is pretty simple: just call keyring.set_password and keyring.get_password:

>>> import keyring
>>> keyring.set_password("system", "username", "password")
>>> keyring.get_password("system", "username")
'password'

Command-line Utility

Keyring supplies a keyring command which is installed with the package. After installing keyring in most environments, the command should be available for setting, getting, and deleting passwords. For more information on usage, invoke with no arguments or with --help as so:

$ keyring --help
$ keyring set system username
Password for 'username' in 'system':
$ keyring get system username
password

The command-line functionality is also exposed as an executable package, suitable for invoking from Python like so:

$ python -m keyring --help
$ python -m keyring set system username
Password for 'username' in 'system':
$ python -m keyring get system username
password

Configuring

The python keyring lib contains implementations for several backends. The library will attempt to automatically choose the most suitable backend for the current environment. Users may also specify the preferred keyring in a config file or by calling the set_keyring() function.

Config file path

The configuration is stored in a file named "keyringrc.cfg" found in a platform-specific location. To determine where the config file is stored, run the following:

python -c "import keyring.util.platform_; print(keyring.util.platform_.config_root())"

Some keyrings also store the keyring data in the file system. To determine where the data files are stored, run:

python -c "import keyring.util.platform_; print(keyring.util.platform_.data_root())"

Config file content

To specify a keyring backend, set the default-keyring option to the full path of the class for that backend, such as keyring.backends.OS_X.Keyring.

If keyring-path is indicated, keyring will add that path to the Python module search path before loading the backend.

For example, this config might be used to load the SimpleKeyring from the simplekeyring module in the ./demo directory (not implemented):

[backend]
default-keyring=simplekeyring.SimpleKeyring
keyring-path=demo

Third-Party Backends

In addition to the backends provided by the core keyring package for the most common and secure use cases, there are additional keyring backend implementations available for other use-cases. Simply install them to make them available:

Write your own keyring backend

The interface for the backend is defined by keyring.backend.KeyringBackend. Every backend should derive from that base class and define a priority attribute and three functions: get_password(), set_password(), and delete_password(). The get_credential() function may be defined if desired.

See the backend module for more detail on the interface of this class.

Keyring employs entry points to allow any third-party package to implement backends without any modification to the keyring itself. Those interested in creating new backends are encouraged to create new, third-party packages in the keyrings namespace, in a manner modeled by the keyrings.alt package. See the setup.cfg file in that project for a hints on how to create the requisite entry points. Backends that prove essential may be considered for inclusion in the core library, although the ease of installing these third-party packages should mean that extensions may be readily available.

To create an extension for Keyring, please submit a pull request to have your extension mentioned as an available extension.

Runtime Configuration

Keyring additionally allows programmatic configuration of the backend calling the api set_keyring(). The indicated backend will subsequently be used to store and retrieve passwords.

To invoke set_keyring:

# define a new keyring class which extends the KeyringBackend
import keyring.backend

class TestKeyring(keyring.backend.KeyringBackend):
    """A test keyring which always outputs same password
    """
    priority = 1

    def set_password(self, servicename, username, password):
        pass

    def get_password(self, servicename, username):
        return "password from TestKeyring"

    def delete_password(self, servicename, username):
        pass

# set the keyring for keyring lib
keyring.set_keyring(TestKeyring())

# invoke the keyring lib
try:
    keyring.set_password("demo-service", "tarek", "passexample")
    print("password stored successfully")
except keyring.errors.PasswordSetError:
    print("failed to store password")
print("password", keyring.get_password("demo-service", "tarek"))

Disabling Keyring

In many cases, uninstalling keyring will never be necessary. Especially on Windows and macOS, the behavior of keyring is usually degenerate, meaning it will return empty values to the caller, allowing the caller to fall back to some other behavior.

In some cases, the default behavior of keyring is undesirable and it would be preferable to disable the keyring behavior altogether. There are several mechanisms to disable keyring:

  • Uninstall keyring. Most applications are tolerant to keyring not being installed. Uninstalling keyring should cause those applications to fall back to the behavior without keyring. This approach affects that Python environment where keyring would otherwise have been installed.
  • Configure the Null keyring in the environment. Set PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring in the environment, and the Null (degenerate) backend will be used. This approach affects all uses of Keyring where that variable is set.
  • Permanently configure the Null keyring for the user by running keyring --disable or python -m keyring --disable. This approach affects all uses of keyring for that user.

Altering Keyring Behavior

Keyring provides a mechanism to alter the keyring's behavior through environment variables. Each backend implements a KeyringBackend.set_properties_from_env, which when invoked will find all environment variables beginning with KEYRING_PROPERTY_{NAME} and will set a property for each {NAME.lower()} on the keyring. This method is invoked during initialization for the default/configured keyring.

This mechanism may be used to set some useful values on various keyrings, including:

  • keychain; macOS, path to an alternate keychain file
  • appid; Linux/SecretService, alternate ID for the application

Using Keyring on Ubuntu 16.04

The following is a complete transcript for installing keyring in a virtual environment on Ubuntu 16.04. No config file was used:

$ sudo apt install python3-venv libdbus-glib-1-dev
$ cd /tmp
$ pyvenv py3
$ source py3/bin/activate
$ pip install -U pip
$ pip install secretstorage dbus-python
$ pip install keyring
$ python
>>> import keyring
>>> keyring.get_keyring()
<keyring.backends.SecretService.Keyring object at 0x7f9b9c971ba8>
>>> keyring.set_password("system", "username", "password")
>>> keyring.get_password("system", "username")
'password'

Using Keyring on headless Linux systems

It is possible to use the SecretService backend on Linux systems without X11 server available (only D-Bus is required). In this case:

Install the GNOME Keyring daemon.

Start a D-Bus session, e.g. run dbus-run-session -- sh and run the following commands inside that shell.

Run gnome-keyring-daemon with --unlock option. The description of that option says:

Read a password from stdin, and use it to unlock the login keyring or create it if the login keyring does not exist.

When that command is started, enter a password into stdin and press Ctrl+D (end of data). After that, the daemon will fork into background (use --foreground option to block).

Now you can use the SecretService backend of Keyring. Remember to run your application in the same D-Bus session as the daemon.

Using Keyring on headless Linux systems in a Docker container

It is possible to use keyring with the SecretService backend in Docker containers as well. All you need to do is install the necessary dependencies and add the --privileged flag to avoid any Operation not permitted errors when attempting to unlock the system's keyring.

The following is a complete transcript for installing keyring on a Ubuntu 18:04 container:

docker run -it -d --privileged ubuntu:18.04

$ apt-get update
$ apt install -y gnome-keyring python3-venv python3-dev
$ python3 -m venv venv
$ source venv/bin/activate # source a virtual environment to avoid polluting your system
$ pip3 install --upgrade pip
$ pip3 install keyring
$ dbus-run-session -- sh # this will drop you into a new D-bus shell
$ echo 'somecredstorepass' | gnome-keyring-daemon --unlock # unlock the system's keyring

$ python
>>> import keyring
>>> keyring.get_keyring()
<keyring.backends.SecretService.Keyring object at 0x7f9b9c971ba8>
>>> keyring.set_password("system", "username", "password")
>>> keyring.get_password("system", "username")
'password'

Integration

API

The keyring lib has a few functions:

  • get_keyring(): Return the currently-loaded keyring implementation.
  • get_password(service, username): Returns the password stored in the active keyring. If the password does not exist, it will return None.
  • get_credential(service, username): Return a credential object stored in the active keyring. This object contains at least username and password attributes for the specified service, where the returned username may be different from the argument.
  • set_password(service, username, password): Store the password in the keyring.
  • delete_password(service, username): Delete the password stored in keyring. If the password does not exist, it will raise an exception.

In all cases, the parameters (service, username, password) should be Unicode text.

Exceptions

The keyring lib raises following exceptions:

  • keyring.errors.KeyringError: Base Error class for all exceptions in keyring lib.
  • keyring.errors.InitError: Raised when the keyring cannot be initialized.
  • keyring.errors.PasswordSetError: Raised when password cannot be set in the keyring.
  • keyring.errors.PasswordDeleteError: Raised when the password cannot be deleted in the keyring.

Get Involved

Python keyring lib is an open community project and eagerly welcomes contributors.

For Enterprise

Available as part of the Tidelift Subscription.

This project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.

Learn more.

Security Contact

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

Security Considerations

Each builtin backend may have security considerations to understand before using this library. Authors of tools or libraries utilizing keyring are encouraged to consider these concerns.

As with any list of known security concerns, this list is not exhaustive. Additional issues can be added as needed.

Making Releases

This project makes use of automated releases continuous integration. The simple workflow is to tag a commit and push it to Github. If it passes tests in CI, it will be automatically deployed to PyPI.

Other things to consider when making a release:

  • Check that the changelog is current for the intended release.

Running Tests

Tests are continuously run in Github Actions.

To run the tests locally, install and invoke tox.

Background

The project was based on Tarek Ziade's idea in this post. Kang Zhang initially carried it out as a Google Summer of Code project, and Tarek mentored Kang on this project.

Windows Credential Locker

  • No analysis has been performed

KDE4 & KDE5 KWallet

  • No analysis has been performed

Freedesktop Secret Service

  • No analysis has been performed

macOS Keychain

  • Any Python script or application can access secrets created by keyring from that same Python executable without the operating system prompting the user for a password. To cause any specific secret to prompt for a password every time it is accessed, locate the credential using the Keychain Access application, and in the Access Control settings, remove Python from the list of allowed applications.

Author: Jaraco
Source Code: https://github.com/jaraco/keyring 
License: MIT License

#python #services 

Keyring: Store and Access Your Passwords Safely

Cómo Crear Un Sitio Web De Cartera Usando HTML, CSS, JavaScript

Si eres un desarrollador web o un diseñador web, es esencial que tengas un sitio web de cartera. Le permite proporcionar información sobre usted y mostrar su mejor trabajo con sus habilidades y experiencia relevantes.

En esta publicación de blog, analizaré algunos de los beneficios de crear un sitio web de cartera. Luego, le mostraré cómo crear un hermoso sitio web de portafolio receptivo para usted usando HTML, CSS, JavaScript y Bootstrap versión 5.

Beneficios de tener un sitio web de cartera

Tener un sitio web de cartera tiene varios beneficios, que incluyen:

  • proporciona una plataforma para mostrar sus habilidades y experiencia relevantes
  • muestra tu personalidad
  • permite que los gerentes de contratación lo encuentren en lugar de que usted se comunique con ellos
  • se le puede buscar fácilmente en motores de búsqueda como Google

¿Qué es Bootstrap?

Bootstrap es un marco CSS front-end popular que se utiliza para desarrollar sitios web receptivos y compatibles con dispositivos móviles. La última versión de Bootstrap es la versión 5. Puede encontrar la documentación oficial de Bootstrap 5 aquí .

Estructura de carpetas

Ahora comenzaremos a trabajar en la creación del sitio web de la cartera.

Primero, vamos a crear la estructura de carpetas. Puede obtener los archivos de inicio del proyecto en GitHub . Además, puede visitar aquí para ver la demostración en vivo de este proyecto.

Captura de pantalla de 2022-01-22-19-10-25

Estructura de carpetas del proyecto

La estructura de carpetas consta de archivos index.html, style.css y script.js y una carpeta de imágenes. Escribiremos todo el CSS en el archivo style.css y el JavaScript en el archivo script.js.

En el archivo index.html, puede ver el código repetitivo HTML con Bootstrap CDN, el kit impresionante de fuentes y un enlace a la hoja de estilo externa y JavaScript.

Aquí, el archivo script.js se carga después de cargar todo el código HTML.

Cómo agregar un menú de navegación a su cartera

Ahora, trabajemos en agregar un menú de navegación en nuestro proyecto. Ayudará a los visitantes a encontrar la información relevante que están buscando.

Usaremos la fixed-topclase de Bootstrap en el elemento de navegación para mantener la barra de navegación en la parte superior de la página. La barra de navegación también tiene una navbar-brandclase donde guardamos el nombre de la persona como marca.

<nav class="navbar navbar-expand-lg fixed-top navbarScroll">
        <div class="container">
            <a class="navbar-brand" href="#">Brad</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item active">
                        <a class="nav-link" href="#home">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#about">About</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#services">Services</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#portfolio">Portfolio</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#contact">Contact</a>
                    </li>
                </ul>
                
            </div>
        </div>
    </nav>

La barra de navegación tiene las siguientes características:

  • Tiene seis enlaces: inicio, acerca de, servicios, cartera, contacto y pie de página.
  • Tiene un fondo transparente. Agregaremos un fondo oscuro en el desplazamiento de la página más adelante.
  • Se alterna en dispositivos más pequeños.

Puede encontrar más detalles sobre las funciones de la barra de navegación de Bootstrap 5 aquí .

Sin embargo, la barra de navegación tiene un problema al desplazarse. Es totalmente transparente en toda la página, lo que provoca problemas de legibilidad. Solucionaremos este problema después de que completemos la sección Servicios para que comprenda el problema correctamente.

Cómo agregar un encabezado de héroe a la cartera

Ahora, agregaremos una imagen de héroe con algo de texto en el centro. Una imagen de héroe es un término de diseño web que se refiere a una imagen de ancho completo de alta calidad que muestra los objetivos principales de la empresa o del individuo, una imagen representativa, una foto u otros elementos llamativos. Ayuda a atraer usuarios a su sitio.

 <!-- main banner -->
    <section class="bgimage" id="home">
        <div class="container-fluid">
            <div class="row">
            <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 hero-text">
                <h2 class="hero_title">Hi, it's me Brad</h2>
                <p class="hero_desc">I am a professional freelancer in New York City</p>
            </div>
            </div>
        </div>
    </section>

 Además, agreguemos el CSS para el código anterior en el archivo style.css:

/* hero background image */
.bgimage {
    height:100vh;
    background: url('images/heroImage.jpeg');
    background-size:cover;
    position:relative;
}
/* text css above hero image*/
.hero_title {
    font-size: 4.5rem;
}
.hero_desc {
    font-size: 2rem;
}
.hero-text {
    text-align: center;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: white;
}

Aquí podemos ver que la sección tiene una identificación llamada bgimageque es responsable de mostrar la imagen del héroe de fondo con todo el ancho. También muestra algo de texto en el centro sobre la imagen de fondo con la ayuda del CSS anterior.

Así es como se ve el sitio hasta ahora con la barra de navegación y la sección principal:

Captura de pantalla de 2022-01-25-10-13-25

Imagen destacada con barra de navegación

Cómo hacer la sección Acerca de

La página Acerca de contiene información importante sobre usted y sus antecedentes. Los visitantes del sitio de su cartera pueden conocerlo a través de la información que proporciona en esta página.

Agregaremos una imagen al lado izquierdo de la fila, y en el lado derecho agregaremos nuestra introducción rápida en esta sección. Vamos a demostrarlo usando el siguiente código:

<!-- about section-->
    <section id="about">
        <div class="container mt-4 pt-4">
            <h1 class="text-center">About Me</h1>
            <div class="row mt-4">
                <div class="col-lg-4">
                    <img src="images/about.jpeg" class= "imageAboutPage" alt="">
                </div>

                <div class="col-lg-8">
                    <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged
                        
                    </p>
                    <div class="row mt-3">
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                    </div>
                    <div class="row mt-3">
                        <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                            Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                        </p>
                    </div>
                </div>
            </div>
    </section>

Agreguemos algo de CSS para la imagen del lado izquierdo:

/* about section image css */
.imageAboutPage {
    width: 100%;
}

Esto creará una sección acerca de. Puede modificar el contenido en función de sus casos de uso. Hemos agregado clases con nombre mt-4y pt-4clase de contenedor que establecerán el margen superior y el relleno superior en 1,5 rem.

La fila tiene dos columnas. Uno tiene la col-lg-4clase para mostrar la imagen que ocupará la columna izquierda con una cuadrícula de 4 partes para pantallas grandes.

A la siguiente columna se le asigna una clase de col-lg-8la cual ocupará la columna de la derecha con una cuadrícula de 8 partes para pantallas más grandes. Para pantallas medianas y pequeñas, se superpondrán entre sí, lo que podemos ver en el siguiente archivo GIF:

acerca de

Acerca de la sección

Cómo hacer la sección de servicios

Esta sección ayuda a convertir a los visitantes del sitio web en clientes potenciales. Aquí es donde explica qué servicios específicos ofrece y dónde clasifica los servicios ofrecidos.

Agreguemos el código para esta sección y describámoslo a continuación:

<!-- services section-->
    <section id="services">
        <div class="container">
            <h1 class="text-center">Services</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class="fas servicesIcon fa-clock"></i>
                            <h4 class="card-title mt-3">Website Development</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-layer-group'></i>
                            <h4 class="card-title mt-3">Website Design</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='far servicesIcon fa-check-circle'></i>
                            <h4 class="card-title mt-3">Website Deployment</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>

            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-search'></i>
                            <h4 class="card-title mt-3">SEO</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-shield-alt'></i>
                            <h4 class="card-title mt-3">DevOps</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-wrench'></i>
                            <h4 class="card-title mt-3">QA</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>
        </div>
    </section>

Dado que este sitio web está dirigido a desarrolladores y diseñadores web, he incluido algunos de los servicios que un desarrollador o diseñador web podría ofrecer.

Hemos utilizado tarjetas de arranque para mostrar servicios. Nuestra sección de servicios tiene 2 filas y 3 columnas cada una. Para pantallas grandes con un ancho mayor o igual a 992 px, se muestran tres tarjetas seguidas. Para pantallas de menos de 992 px de ancho, solo se muestra una tarjeta en una fila.

Puede encontrar más información sobre los puntos de interrupción de arranque aquí .

Además, se agregan fuentes en cada tarjeta para que se vean mejor.

Sin CSS, la sección de servicios se vería así:

Captura de pantalla de 2022-01-23-14-01-00

Por lo tanto, agreguemos algo de CSS para aumentar el tamaño de fuente del icono de fuente y la altura de la tarjeta y agreguemos un poco de color adicional cuando un usuario pase el mouse sobre una tarjeta.

/* services section css */
.servicesText.card {
    height: 280px;
    cursor: pointer;
  }
.servicesIcon {
    font-size: 36px;
    text-align: center;
    width: 100%;
}
.card-title {
    text-align: center;
}
.card:hover .servicesIcon {
    color: #008000;
}
.servicesText:hover {
    border: 1px solid #008000;
}

Así luce ahora nuestra sección de servicios:

servicios

Servicios 

Cómo agregar un color de fondo oscuro a la barra de navegación en el desplazamiento de página

Si observa correctamente el gif anterior, verá que la barra de navegación es transparente en toda la página, lo que provoca problemas de legibilidad. Entonces, trabajemos para solucionar este problema.

Escribiremos algo de JavaScript y CSS para resolver este problema. Agregaremos una navbarDarkclase para mostrar un color de fondo oscuro para la barra de navegación en el desplazamiento de la página.

Para eso necesitamos ir al archivo script.js y agregar el siguiente código:

// add class navbarDark on navbar scroll
const header = document.querySelector('.navbar');

window.onscroll = function() {
    var top = window.scrollY;
    if(top >=100) {
        header.classList.add('navbarDark');
    }
    else {
        header.classList.remove('navbarDark');
    }
}

Ahora, analicemos el código anterior:

  • El encabezado contiene el valor del elemento de navegación ya que el método querySelector devuelve el primer elemento que coincide con el selector de CSS (que es .navbaren este caso).
  • window.onscroll se activa cuando ocurre el evento de desplazamiento.
  • window.scrollYdevuelve el número de píxeles que el documento se desplaza verticalmente y su valor se asigna a una variable llamada top.
  • Si el valor de topes mayor o igual a 100, agrega una clase de navbarDarkal encabezado.

Agreguemos rápidamente CSS para la navbarDarkclase. Para eso, ve a tu archivo style.css y agrega el siguiente código:

/* display background color black on navbar scroll */
.navbarScroll.navbarDark {
    background-color: black;
}

Así es como se verá la barra de navegación ahora:

barra de navegación

Color de fondo oscuro en la barra de navegación al desplazarse por la página

Cómo construir la sección de cartera

Esta sección incluye tu mejor trabajo. La gente puede ver lo que eres capaz de hacer, y mostrar un trabajo anterior sólido definitivamente atraerá a más clientes o reclutadores potenciales. Así que solo agregue su mejor trabajo en esta sección.

Usaremos tarjetas Bootstrap para mostrar los proyectos de la cartera. Habrá 2 filas y cada fila tendrá 3 columnas de cartas.

Este será el código para la sección de cartera:

<!-- portfolio section-->
    <section id="portfolio">
        <div class="container mt-3">
            <h1 class="text-center">Portfolio</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">YouTube Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Quiz App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage3.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Product Landing Page</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <br>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Messaging Service</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Twitter Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Blog App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
    </section>

Cada tarjeta tiene una imagen, título, descripción y enlace a los proyectos. Se muestran tres tarjetas en una fila para pantallas grandes que tienen puntos de interrupción de ≥ 992 px de ancho, pero para pantallas < 992 px de ancho solo se muestra una tarjeta en una fila.

El siguiente GIF muestra cómo se ve ahora la sección de cartera:

portafolio

portafolio

Cómo construir la sección de contacto

Debe incluir su información de contacto en esta sección para que los visitantes puedan contactarlo si desean contratarlo.

Nuestra sección de contacto incluirá 2 columnas en una sola fila: mapas de Google para la ubicación y un formulario de contacto.

Para incrustar el mapa de Google, debe seguir estos pasos:

  • vaya a https://www.embed-map.com
  • Ingresa tu ubicación
  • haga clic en el botón Generar código HTML que le proporcionará su código HTML de mapa de Google

Nuestro código se verá así con el formulario de contacto incluido:

<!-- contact section-->
    <section id="contact">
        <div class="container mt-3 contactContent">
            <h1 class="text-center">Contact Me</h1>

            <div class="row mt-4">
                <div class="col-lg-6">
                    <!-- to edit google map goto https://www.embed-map.com type your location, generate html code and copy the html  -->
                    <div style="max-width:100%;overflow:hidden;color:red;width:500px;height:500px;">
                        <div id="embedmap-canvas" style="height:100%; width:100%;max-width:100%;">
                            <iframe style="height:100%;width:100%;border:0;" frameborder="0" src="https://www.google.com/maps/embed/v1/place?q=new+york&key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8">
                            </iframe>
                        </div>
                        <a class="googlemaps-html" href="https://www.embed-map.com" id="get-data-forembedmap">https://www.embed-map.com</a>
                        <style>#embedmap-canvas img{max-width:none!important;background:none!important;font-size: inherit;font-weight:inherit;}
                        </style>
                    </div>
                </div>

                <div class="col-lg-6">
                    <!-- form fields -->
                    <form>
                        <input type="text" class="form-control form-control-lg" placeholder="Name">
                        <input type="email" class="form-control mt-3" placeholder="Email">
                        <input type="text" class="form-control mt-3" placeholder="Subject">
                        <div class="mb-3 mt-3">
                            <textarea class="form-control" rows="5" id="comment" name="text" placeholder="Project Details"></textarea>
                        </div>
                    </form>
                    <button type="button" class="btn btn-success mt-3">Contact Me</button>
                    
                </div>

            </div>
        </div>
    </section>

La primera columna mostrará el mapa de Google y la siguiente mostrará el formulario de contacto.

El formulario tiene cuatro campos de formulario diferentes: nombre, correo electrónico, asunto y detalles del proyecto. El formulario no envía la solicitud en sí. Deberá conectarlo con cualquier idioma de back-end. O simplemente puede usar el formulario Netlify o el formulario Formspree para esto.

Así aparecerá la sección de contacto:

Captura de pantalla de 2022-01-25-11-31-56

Sección de contacto

Cómo construir la sección de pie de página

Ahora hemos llegado a la última sección de esta publicación, que es la sección de pie de página. Ya hemos agregado un enlace a la fuente Awesome CDN en el archivo index.html.

En el pie de página, agregaremos enlaces a nuestras redes sociales a través de íconos impresionantes de fuentes.

 <!-- footer section-->
    <footer id="footer">
        <div class="container-fluid">
            <!-- social media icons -->
            <div class="social-icons mt-4">
                <a href="https://www.facebook.com/" target="_blank"><i class="fab fa-facebook"></i></a>
                <a href="https://www.instagram.com/" target="_blank"><i class="fab fa-instagram"></i></a>
                <a href="https://www.twitter.com/" target="_blank"><i class="fab fa-twitter"></i></a>
                <a href="https://www.linkedin.com/" target="_blank"><i class="fab fa-linkedin"></i></a>
                <a href="https://www.twitch.tv/" target="_blank"><i class="fab fa-twitch"></i></a>
            </div>
        </div>
    </footer>

Sin el CSS, nuestro pie de página se verá así:

Captura de pantalla de 2022-01-23-17-56-37

pie de página sin estilo

Así que agreguemos algo de estilo al pie de página con este código:

/* social media icons styling */
.social-icons {
    font-size: 36px;
    cursor: pointer;
}
.fa-facebook:hover,.fa-instagram:hover,.fa-twitter:hover,.fa-linkedin:hover, .fa-twitch:hover {
    color: #008000;
}
.fab {
    color: #000000;
}
/* footer styling */
#footer {
    background-color: #808080;
    text-align: center;
}

Los íconos ahora se muestran en el centro con un efecto de desplazamiento que podemos ver en el siguiente archivo GIF.

pie de página

Pie de página

Toques finales

Para agregar algo de espacio entre todas las secciones, agreguemos un poco más de estilo:

/* spacing on all sections */
#about, #services, #portfolio, #contact {
    margin-top: 4rem;
    padding-top: 4rem;
}
#contact {
    padding-bottom: 4rem;
}

Ahora hemos terminado de hacer nuestro sitio web de cartera completo.

Puede encontrar el código fuente completo de este proyecto aquí .

Conclusión

Así es como puede crear un sitio web de cartera receptivo completo utilizando HTML, CSS, JavaScript y Bootstrap 5.

En esta publicación de blog, vimos algunos de los beneficios de crear un sitio web de cartera para desarrolladores y diseñadores web. Dividimos todo el sitio web en diferentes secciones y discutimos cada una individualmente a medida que la construíamos.

Puede personalizar este sitio web en función de sus propios casos de uso.

Espero que hayas encontrado útil esta publicación.

¡Feliz codificación!  

Enlace: https://www.freecodecamp.org/news/how-to-create-a-portfolio-website-using-html-css-javascript-and-bootstrap/

#html  #css  #javascript 

Cómo Crear Un Sitio Web De Cartera Usando HTML, CSS, JavaScript
宇野  和也

宇野 和也

1643369460

HTML、CSS、JavaScript、Bootstrap5を使用してポートフォリオWebサイトを作成する

あなたがウェブ開発者またはウェブデザイナーであるならば、あなたがポートフォリオウェブサイトを持っていることはあなたにとって不可欠です。それはあなたがあなた自身についての情報を提供し、あなたの関連するスキルと経験であなたの最高の仕事を紹介することを可能にします。

このブログ投稿では、ポートフォリオWebサイトを作成する利点のいくつかについて説明します。次に、HTML、CSS、JavaScript、およびBootstrapバージョン5を使用して、美しいレスポンシブポートフォリオWebサイトを自分で作成する方法を紹介します。

ポートフォリオウェブサイトを持つことの利点

ポートフォリオWebサイトを持つことには、次のようないくつかの利点があります。

  • 関連するスキルと経験を紹介するためのプラットフォームを提供します
  • それはあなたの性格を示しています
  • 採用担当マネージャーは、あなたが彼らに連絡する代わりにあなたを見つけることができます
  • あなたはグーグルのような検索エンジンで簡単に検索できます

ブートストラップとは何ですか?

Bootstrapは、レスポンシブでモバイルフレンドリーなWebサイトを開発するために使用される人気のあるフロントエンドCSSフレームワークです。Bootstrapの最新リリースはバージョン5です。Bootstrap5の公式ドキュメントはここにあります

フォルダ構造

ポートフォリオWebサイトの作成に取り掛かります。

まず、フォルダ構造を作成しましょう。プロジェクトスターターファイルはGitHubで入手できます。また、ここにアクセスして、このプロジェクトのライブデモを見ることができます。

スクリーンショット-2022-01-22-19-10-25から

プロジェクトフォルダの構造

フォルダ構造は、index.html、style.css、script.jsファイルとimagesフォルダで構成されています。すべてのCSSをstyle.cssファイルに記述し、JavaScriptをscript.jsファイルに記述します。

index.htmlファイルには、Bootstrap CDN、font awesomeキット、および外部スタイルシートとJavaScriptへのリンクを含むHTMLボイラープレートコードが表示されます。

ここでは、すべてのHTMLコードをロードした後にscript.jsファイルがロードされます。

ポートフォリオにナビゲーションメニューを追加する方法

それでは、プロジェクトにナビゲーションメニューを追加してみましょう。それは訪問者が彼らが探している関連情報を見つけるのを助けるでしょう。

nav要素でBootstrapのfixed-topクラスを使用して、navbarをページの上部に保持します。ナビゲーションバーにはnavbar-brand、その人の名前をブランドとして保持するクラスもあります。

<nav class="navbar navbar-expand-lg fixed-top navbarScroll">
        <div class="container">
            <a class="navbar-brand" href="#">Brad</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item active">
                        <a class="nav-link" href="#home">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#about">About</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#services">Services</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#portfolio">Portfolio</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#contact">Contact</a>
                    </li>
                </ul>
                
            </div>
        </div>
    </nav>

ナビゲーションバーには次の機能があります。

  • ホーム、アバウト、サービス、ポートフォリオ、連絡先、フッターの6つのリンクがあります
  • 背景は透明です。後でページスクロールに暗い背景を追加します。
  • 小さいデバイスで切り替わります

Bootstrap 5ナビゲーションバー機能の詳細については、こちらをご覧ください。

ただし、スクロール中にナビゲーションバーに問題があります。ページ全体が完全に透過的であるため、読みやすさの問題が発生します。問題を正しく理解できるように、サービスセクションを完了した後、この問題を修正します。

ポートフォリオにヒーローヘッダーを追加する方法

次に、中央にテキストを含むヒーロー画像を追加します。ヒーロー画像は、会社または個人の主な目標、代表的な画像、写真、またはその他の人目を引く要素を表示する高品質の全幅画像を指すWebデザイン用語です。それはあなたのサイトにユーザーを引き付けるのに役立ちます。

 <!-- main banner -->
    <section class="bgimage" id="home">
        <div class="container-fluid">
            <div class="row">
            <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 hero-text">
                <h2 class="hero_title">Hi, it's me Brad</h2>
                <p class="hero_desc">I am a professional freelancer in New York City</p>
            </div>
            </div>
        </div>
    </section>

 また、上記のコードのCSSをstyle.cssファイルに追加しましょう。

/* hero background image */
.bgimage {
    height:100vh;
    background: url('images/heroImage.jpeg');
    background-size:cover;
    position:relative;
}
/* text css above hero image*/
.hero_title {
    font-size: 4.5rem;
}
.hero_desc {
    font-size: 2rem;
}
.hero-text {
    text-align: center;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: white;
}

ここでは、セクションにbgimage、背景のヒーロー画像を全幅で表示するための名前のIDがあることがわかります。また、上記のCSSを使用して、背景画像の上の中央にテキストを表示します。

これは、ナビゲーションバーとヒーローセクションでこれまでのところサイトがどのように見えるかです:

スクリーンショット-2022-01-25-10-13-25から

ナビゲーションバー付きのヒーロー画像

アバウトセクションの作り方

Aboutページには、あなたとあなたの経歴に関する重要な情報が含まれています。あなたのポートフォリオサイトへの訪問者は、あなたがこのページで提供する情報を通してあなたを知ることができます。

行の左側に画像を追加し、右側にこのセクションで簡単な紹介を追加します。以下のコードを使用してそれをデモンストレーションしましょう:

<!-- about section-->
    <section id="about">
        <div class="container mt-4 pt-4">
            <h1 class="text-center">About Me</h1>
            <div class="row mt-4">
                <div class="col-lg-4">
                    <img src="images/about.jpeg" class= "imageAboutPage" alt="">
                </div>

                <div class="col-lg-8">
                    <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged
                        
                    </p>
                    <div class="row mt-3">
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                        <div class="col-md-6">
                            <ul>
                                <li>Name: David Parker</li>
                                <li>Age: 28</li>
                                <li>Occupation: Web Developer</li>

                            </ul>
                        </div>
                    </div>
                    <div class="row mt-3">
                        <p> Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                            Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.
                        </p>
                    </div>
                </div>
            </div>
    </section>

左側の画像にCSSを追加しましょう。

/* about section image css */
.imageAboutPage {
    width: 100%;
}

これにより、aboutセクションが作成されます。ユースケースに基づいてコンテンツを変更できます。マージントップとパディングトップを1.5レムに設定するコンテナクラスという名前mt-4のクラスを追加しました。pt-4

行には2つの列があります。1つは、col-lg-4大画面用の4つの部分からなるグリッドで左の列を占める画像を表示するためのクラスです。

次の列にはクラスが割り当てられ、そのクラスはcol-lg-8、より大きな画面用に8つの部分からなるグリッドで右側の列を占めます。中画面と小画面の場合、それらは互いに重なり合います。これは、以下のGIFファイルで確認できます。

約

セクションについて

サービスセクションの作り方

このセクションは、Webサイトの訪問者を潜在的なクライアントに変えるのに役立ちます。ここでは、提供する特定のサービスを説明し、提供するサービスをニッチに絞り込みます。

このセクションのコードを追加して、以下に説明しましょう。

<!-- services section-->
    <section id="services">
        <div class="container">
            <h1 class="text-center">Services</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class="fas servicesIcon fa-clock"></i>
                            <h4 class="card-title mt-3">Website Development</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-layer-group'></i>
                            <h4 class="card-title mt-3">Website Design</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='far servicesIcon fa-check-circle'></i>
                            <h4 class="card-title mt-3">Website Deployment</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>

            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-search'></i>
                            <h4 class="card-title mt-3">SEO</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-shield-alt'></i>
                            <h4 class="card-title mt-3">DevOps</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card servicesText">
                        <div class="card-body">
                            <i class='fas servicesIcon fa-wrench'></i>
                            <h4 class="card-title mt-3">QA</h4>
                            <p class="card-text mt-3">Some quick example text to build on the card title and make up the bulk of the card's content.
                                Some quick example text to build on the card title and make up the bulk of the card's content.
                            </p>
                        </div>
                    </div>  
                </div>
            </div>
        </div>
    </section>

このWebサイトは、Web開発者およびデザイナーを対象としているため、Web開発者またはデザイナーが提供する可能性のあるサービスの一部を含めました。

サービスを表示するためにブートストラップカードを使用しました。サービスセクションには、それぞれ2行3列あります。幅が992px以上の大画面の場合、3枚のカードが連続して表示されます。幅が992px未満の画面の場合、1枚のカードのみが連続して表示されます。

ブートストラップブレークポイントの詳細については、こちらをご覧ください。

また、見栄えを良くするために、各カードにフォントが追加されています。

CSSがない場合、サービスセクションは次のようになります。

スクリーンショット-2022-01-23-14-01-00から

そこで、CSSを追加して、フォントアイコンのフォントサイズとカードの高さを増やし、ユーザーがカードにカーソルを合わせたときに色を追加しましょう。

/* services section css */
.servicesText.card {
    height: 280px;
    cursor: pointer;
  }
.servicesIcon {
    font-size: 36px;
    text-align: center;
    width: 100%;
}
.card-title {
    text-align: center;
}
.card:hover .servicesIcon {
    color: #008000;
}
.servicesText:hover {
    border: 1px solid #008000;
}

これが私たちのサービスセクションが今どのように見えるかです:

サービス

サービス 

ページスクロールのナビゲーションバーに暗い背景色を追加する方法

上記のgifを適切に調べると、ナビゲーションバーがページ全体で透明であることがわかり、読みやすさの問題が発生します。それでは、この問題の修正に取り組みましょう。

この問題を解決するために、JavaScriptとCSSを作成します。navbarDarkページスクロールでナビゲーションバーの背景色を暗くするために、クラスを追加します。

そのためには、script.jsファイルに移動して、次のコードを追加する必要があります。

// add class navbarDark on navbar scroll
const header = document.querySelector('.navbar');

window.onscroll = function() {
    var top = window.scrollY;
    if(top >=100) {
        header.classList.add('navbarDark');
    }
    else {
        header.classList.remove('navbarDark');
    }
}

それでは、上記のコードを分解してみましょう。

  • querySelectorメソッドはCSSセレクター(.navbarこの場合)に一致する最初の要素を返すため、ヘッダーはnav要素の値を保持します。
  • window.onscroll スクロールイベントが発生すると起動します。
  • window.scrollYドキュメントが垂直方向にスクロールされ、その値が。という名前の変数に割り当てられているピクセル数を返しますtop
  • の値がtop100以上の場合navbarDark、ヘッダーにのクラスが追加されます。

navbarDarkクラスのCSSを簡単に追加しましょう。そのためには、style.cssファイルに移動し、次のコードを追加します。

/* display background color black on navbar scroll */
.navbarScroll.navbarDark {
    background-color: black;
}

これがナビゲーションバーの外観です。

ナビゲーションバー

ページスクロールのナビゲーションバーの暗い背景色

ポートフォリオセクションの構築方法

このセクションには、あなたの最高の作品が含まれています。人々はあなたが何ができるかを見ることができ、強力な過去の仕事を紹介することは間違いなくより多くの潜在的なクライアントやリクルーターを引き付けるでしょう。したがって、このセクションには最高の作品のみを追加してください。

Bootstrapカードを使用してポートフォリオプロジェクトを表示します。2行あり、各行には3列のカードがあります。

これはポートフォリオセクションのコードになります。

<!-- portfolio section-->
    <section id="portfolio">
        <div class="container mt-3">
            <h1 class="text-center">Portfolio</h1>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">YouTube Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Quiz App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage3.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Product Landing Page</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <br>
            <div class="row">
                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Messaging Service</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage1.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Twitter Clone</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="col-lg-4 mt-4">
                    <div class="card portfolioContent">
                        <img class="card-img-top" src="images/portfolioImage4.jpg" alt="Card image" style="width:100%">
                        <div class="card-body">
                            <h4 class="card-title">Blog App</h4>
                            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
                            <div class="text-center">
                                <a href="#" class="btn btn-success">Link</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
    </section>

各カードには、画像、タイトル、説明、およびプロジェクトへのリンクがあります。ブレークポイントの幅が992px以上の大画面の場合、3枚のカードが連続して表示されますが、幅が992px未満の画面の場合、1枚のカードのみが連続して表示されます。

以下のGIFは、ポートフォリオセクションが現在どのように見えるかを示しています。

ポートフォリオ

ポートフォリオ

連絡先セクションの作成方法

訪問者があなたを雇いたい場合にあなたに連絡できるように、このセクションにあなたの連絡先情報を含める必要があります。

お問い合わせセクションには、1行に2つの列が含まれます。場所のGoogleマップとお問い合わせフォームです。

Googleマップを埋め込むには、次の手順に従う必要があります。

  • https://www.embed-map.comにアクセスします
  • あなたの場所を入力してください
  • GoogleマップのHTMLコードを提供する[ HTMLコードの生成]ボタンをクリックします

コードは次のようになり、お問い合わせフォームが含まれています。

<!-- contact section-->
    <section id="contact">
        <div class="container mt-3 contactContent">
            <h1 class="text-center">Contact Me</h1>

            <div class="row mt-4">
                <div class="col-lg-6">
                    <!-- to edit google map goto https://www.embed-map.com type your location, generate html code and copy the html  -->
                    <div style="max-width:100%;overflow:hidden;color:red;width:500px;height:500px;">
                        <div id="embedmap-canvas" style="height:100%; width:100%;max-width:100%;">
                            <iframe style="height:100%;width:100%;border:0;" frameborder="0" src="https://www.google.com/maps/embed/v1/place?q=new+york&key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8">
                            </iframe>
                        </div>
                        <a class="googlemaps-html" href="https://www.embed-map.com" id="get-data-forembedmap">https://www.embed-map.com</a>
                        <style>#embedmap-canvas img{max-width:none!important;background:none!important;font-size: inherit;font-weight:inherit;}
                        </style>
                    </div>
                </div>

                <div class="col-lg-6">
                    <!-- form fields -->
                    <form>
                        <input type="text" class="form-control form-control-lg" placeholder="Name">
                        <input type="email" class="form-control mt-3" placeholder="Email">
                        <input type="text" class="form-control mt-3" placeholder="Subject">
                        <div class="mb-3 mt-3">
                            <textarea class="form-control" rows="5" id="comment" name="text" placeholder="Project Details"></textarea>
                        </div>
                    </form>
                    <button type="button" class="btn btn-success mt-3">Contact Me</button>
                    
                </div>

            </div>
        </div>
    </section>

最初の列にはGoogleマップが表示され、次の列にはお問い合わせフォームが表示されます。

フォームには、名前、電子メール、件名、プロジェクトの詳細の4つの異なるフォームフィールドがあります。フォームはリクエスト自体を送信しません。バックエンド言語に接続する必要があります。または、 NetlifyフォームまたはFormspreeフォームを使用することもできます

連絡先セクションは次のように表示されます。

スクリーンショット-2022-01-25-11-31-56から

連絡先セクション

フッターセクションの作成方法

これで、この投稿の最後のセクションであるフッターセクションに到達しました。index.htmlファイルにfontawesomeCDNへのリンクを すでに追加しています。

フッターでは、フォントの素晴らしいアイコンを介してソーシャルメディアへのリンクを追加します。

 <!-- footer section-->
    <footer id="footer">
        <div class="container-fluid">
            <!-- social media icons -->
            <div class="social-icons mt-4">
                <a href="https://www.facebook.com/" target="_blank"><i class="fab fa-facebook"></i></a>
                <a href="https://www.instagram.com/" target="_blank"><i class="fab fa-instagram"></i></a>
                <a href="https://www.twitter.com/" target="_blank"><i class="fab fa-twitter"></i></a>
                <a href="https://www.linkedin.com/" target="_blank"><i class="fab fa-linkedin"></i></a>
                <a href="https://www.twitch.tv/" target="_blank"><i class="fab fa-twitch"></i></a>
            </div>
        </div>
    </footer>

CSSがない場合、フッターは次のようになります。

スクリーンショット-2022-01-23-17-56-37から

スタイリングなしのフッター??

それでは、このコードを使用してフッターにスタイルを追加しましょう。

/* social media icons styling */
.social-icons {
    font-size: 36px;
    cursor: pointer;
}
.fa-facebook:hover,.fa-instagram:hover,.fa-twitter:hover,.fa-linkedin:hover, .fa-twitch:hover {
    color: #008000;
}
.fab {
    color: #000000;
}
/* footer styling */
#footer {
    background-color: #808080;
    text-align: center;
}

アイコンが中央に表示され、ホバー効果が表示されます。これは、以下のGIFファイルで確認できます。

フッター

フッター

最後の仕上げ

すべてのセクションの間に間隔を追加するために、さらにスタイルを追加しましょう。

/* spacing on all sections */
#about, #services, #portfolio, #contact {
    margin-top: 4rem;
    padding-top: 4rem;
}
#contact {
    padding-bottom: 4rem;
}

これで、完全なポートフォリオWebサイトの作成が完了しました。

このプロジェクトの完全なソースコードはここにあります

結論

これは、HTML、CSS、JavaScript、およびBootstrap5を使用して完全なレスポンシブポートフォリオWebサイトを作成する方法です。

このブログ投稿では、Web開発者とデザイナーのためのポートフォリオWebサイトを作成することの利点のいくつかを見ました。Webサイト全体をさまざまなセクションに分割し、構築時にそれぞれについて個別に説明しました。

このWebサイトは、独自のユースケースに基づいてカスタマイズできます。

この投稿がお役に立てば幸いです。

ハッピーコーディング!  

リンク:https ://www.freecodecamp.org/news/how-to-create-a-portfolio-website-using-html-css-javascript-and-bootstrap/

#html  #css  #javascript 

HTML、CSS、JavaScript、Bootstrap5を使用してポートフォリオWebサイトを作成する